diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 16 |
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; |