aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-06-26 07:57:28 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 13:48:17 -0400
commit4552d5dc08b79868829b4be8951b29b07284753f (patch)
tree7b25695b4c0e1917fc80e8dd4bc494de36320ccc /kernel/module.c
parent2b28592b07223d7fc0691ce3fe57d495dc9cbe3a (diff)
[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>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/kernel/module.c b/kernel/module.c
index d75275de1c28..08811e26ac9d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -40,6 +40,7 @@
40#include <linux/string.h> 40#include <linux/string.h>
41#include <linux/sched.h> 41#include <linux/sched.h>
42#include <linux/mutex.h> 42#include <linux/mutex.h>
43#include <linux/unwind.h>
43#include <asm/uaccess.h> 44#include <asm/uaccess.h>
44#include <asm/semaphore.h> 45#include <asm/semaphore.h>
45#include <asm/cacheflush.h> 46#include <asm/cacheflush.h>
@@ -1051,6 +1052,8 @@ static void free_module(struct module *mod)
1051 remove_sect_attrs(mod); 1052 remove_sect_attrs(mod);
1052 mod_kobject_remove(mod); 1053 mod_kobject_remove(mod);
1053 1054
1055 unwind_remove_table(mod->unwind_info, 0);
1056
1054 /* Arch-specific cleanup. */ 1057 /* Arch-specific cleanup. */
1055 module_arch_cleanup(mod); 1058 module_arch_cleanup(mod);
1056 1059
@@ -1412,7 +1415,7 @@ static struct module *load_module(void __user *umod,
1412 unsigned int i, symindex = 0, strindex = 0, setupindex, exindex, 1415 unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
1413 exportindex, modindex, obsparmindex, infoindex, gplindex, 1416 exportindex, modindex, obsparmindex, infoindex, gplindex,
1414 crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, 1417 crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
1415 gplfuturecrcindex; 1418 gplfuturecrcindex, unwindex = 0;
1416 struct module *mod; 1419 struct module *mod;
1417 long err = 0; 1420 long err = 0;
1418 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1421 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1502,6 +1505,9 @@ static struct module *load_module(void __user *umod,
1502 versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); 1505 versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
1503 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); 1506 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
1504 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); 1507 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
1508#ifdef ARCH_UNWIND_SECTION_NAME
1509 unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);
1510#endif
1505 1511
1506 /* Don't keep modinfo section */ 1512 /* Don't keep modinfo section */
1507 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 1513 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -1510,6 +1516,8 @@ static struct module *load_module(void __user *umod,
1510 sechdrs[symindex].sh_flags |= SHF_ALLOC; 1516 sechdrs[symindex].sh_flags |= SHF_ALLOC;
1511 sechdrs[strindex].sh_flags |= SHF_ALLOC; 1517 sechdrs[strindex].sh_flags |= SHF_ALLOC;
1512#endif 1518#endif
1519 if (unwindex)
1520 sechdrs[unwindex].sh_flags |= SHF_ALLOC;
1513 1521
1514 /* Check module struct version now, before we try to use module. */ 1522 /* Check module struct version now, before we try to use module. */
1515 if (!check_modstruct_version(sechdrs, versindex, mod)) { 1523 if (!check_modstruct_version(sechdrs, versindex, mod)) {
@@ -1738,6 +1746,11 @@ static struct module *load_module(void __user *umod,
1738 goto arch_cleanup; 1746 goto arch_cleanup;
1739 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 1747 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
1740 1748
1749 /* Size of section 0 is 0, so this works well if no unwind info. */
1750 mod->unwind_info = unwind_add_table(mod,
1751 (void *)sechdrs[unwindex].sh_addr,
1752 sechdrs[unwindex].sh_size);
1753
1741 /* Get rid of temporary copy */ 1754 /* Get rid of temporary copy */
1742 vfree(hdr); 1755 vfree(hdr);
1743 1756
@@ -1836,6 +1849,7 @@ sys_init_module(void __user *umod,
1836 mod->state = MODULE_STATE_LIVE; 1849 mod->state = MODULE_STATE_LIVE;
1837 /* Drop initial reference. */ 1850 /* Drop initial reference. */
1838 module_put(mod); 1851 module_put(mod);
1852 unwind_remove_table(mod->unwind_info, 1);
1839 module_free(mod, mod->module_init); 1853 module_free(mod, mod->module_init);
1840 mod->module_init = NULL; 1854 mod->module_init = NULL;
1841 mod->init_size = 0; 1855 mod->init_size = 0;