[PATCH] x86_64: reliable stack trace support
These are the generic bits needed to enable reliable stack traces based on Dwarf2-like (.eh_frame) unwind information. Subsequent patches will enable x86-64 and i386 to make use of this. Thanks to Andi Kleen and Ingo Molnar, who pointed out several possibilities for improvement. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
2b28592b07
commit
4552d5dc08
@@ -32,6 +32,7 @@ extern const char linux_banner[];
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
|
||||
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
|
||||
|
||||
#define KERN_EMERG "<0>" /* system is unusable */
|
||||
#define KERN_ALERT "<1>" /* action must be taken immediately */
|
||||
@@ -336,6 +337,12 @@ struct sysinfo {
|
||||
/* Force a compilation error if condition is true */
|
||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||
|
||||
/* Force a compilation error if condition is true, but also produce a
|
||||
result (of value 0 and type size_t), so the expression can be used
|
||||
e.g. in a structure initializer (or where-ever else comma expressions
|
||||
aren't permitted). */
|
||||
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
|
||||
|
||||
/* Trap pasters of __FUNCTION__ at compile-time */
|
||||
#define __FUNCTION__ (__func__)
|
||||
|
||||
|
||||
@@ -285,6 +285,9 @@ struct module
|
||||
/* The size of the executable code in each section. */
|
||||
unsigned long init_text_size, core_text_size;
|
||||
|
||||
/* The handle returned from unwind_add_table. */
|
||||
void *unwind_info;
|
||||
|
||||
/* Arch-specific module values */
|
||||
struct mod_arch_specific arch;
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef _LINUX_UNWIND_H
|
||||
#define _LINUX_UNWIND_H
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002-2006 Novell, Inc.
|
||||
* Jan Beulich <jbeulich@novell.com>
|
||||
* This code is released under version 2 of the GNU GPL.
|
||||
*
|
||||
* A simple API for unwinding kernel stacks. This is used for
|
||||
* debugging and error reporting purposes. The kernel doesn't need
|
||||
* full-blown stack unwinding with all the bells and whistles, so there
|
||||
* is not much point in implementing the full Dwarf2 unwind API.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
struct module;
|
||||
|
||||
#ifdef CONFIG_STACK_UNWIND
|
||||
|
||||
#include <asm/unwind.h>
|
||||
|
||||
#ifndef ARCH_UNWIND_SECTION_NAME
|
||||
#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize unwind support.
|
||||
*/
|
||||
extern void unwind_init(void);
|
||||
|
||||
extern void *unwind_add_table(struct module *,
|
||||
const void *table_start,
|
||||
unsigned long table_size);
|
||||
|
||||
extern void unwind_remove_table(void *handle, int init_only);
|
||||
|
||||
extern int unwind_init_frame_info(struct unwind_frame_info *,
|
||||
struct task_struct *,
|
||||
/*const*/ struct pt_regs *);
|
||||
|
||||
/*
|
||||
* Prepare to unwind a blocked task.
|
||||
*/
|
||||
extern int unwind_init_blocked(struct unwind_frame_info *,
|
||||
struct task_struct *);
|
||||
|
||||
/*
|
||||
* Prepare to unwind the currently running thread.
|
||||
*/
|
||||
extern int unwind_init_running(struct unwind_frame_info *,
|
||||
asmlinkage void (*callback)(struct unwind_frame_info *,
|
||||
void *arg),
|
||||
void *arg);
|
||||
|
||||
/*
|
||||
* Unwind to previous to frame. Returns 0 if successful, negative
|
||||
* number in case of an error.
|
||||
*/
|
||||
extern int unwind(struct unwind_frame_info *);
|
||||
|
||||
/*
|
||||
* Unwind until the return pointer is in user-land (or until an error
|
||||
* occurs). Returns 0 if successful, negative number in case of
|
||||
* error.
|
||||
*/
|
||||
extern int unwind_to_user(struct unwind_frame_info *);
|
||||
|
||||
#else
|
||||
|
||||
struct unwind_frame_info {};
|
||||
|
||||
static inline void unwind_init(void) {}
|
||||
|
||||
static inline void *unwind_add_table(struct module *mod,
|
||||
const void *table_start,
|
||||
unsigned long table_size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void unwind_remove_table(void *handle, int init_only)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int unwind_init_frame_info(struct unwind_frame_info *info,
|
||||
struct task_struct *tsk,
|
||||
const struct pt_regs *regs)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int unwind_init_blocked(struct unwind_frame_info *info,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int unwind_init_running(struct unwind_frame_info *info,
|
||||
asmlinkage void (*cb)(struct unwind_frame_info *,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int unwind(struct unwind_frame_info *info)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int unwind_to_user(struct unwind_frame_info *info)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_UNWIND_H */
|
||||
Reference in New Issue
Block a user