Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4552d5dc authored by Jan Beulich's avatar Jan Beulich Committed by Linus Torvalds
Browse files

[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: default avatarJan Beulich <jbeulich@novell.com>
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2b28592b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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__)

+3 −0
Original line number Diff line number Diff line
@@ -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;

include/linux/unwind.h

0 → 100644
+119 −0
Original line number Diff line number Diff line
#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 */
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@
#include <linux/rmap.h>
#include <linux/mempolicy.h>
#include <linux/key.h>
#include <linux/unwind.h>

#include <asm/io.h>
#include <asm/bugs.h>
@@ -482,6 +483,7 @@ asmlinkage void __init start_kernel(void)
		   __stop___param - __start___param,
		   &unknown_bootoption);
	sort_main_extable();
	unwind_init();
	trap_init();
	rcu_init();
	init_IRQ();
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_STACK_UNWIND) += unwind.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
Loading