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; |
