When booting, initialize eh_frame for use in the DWARF unwinder. Do the same for every coming module's info. And destroy the information when a module is going away. Signed-off-by: Jiri Slaby <jslaby@xxxxxxx> Cc: Jessica Yu <jeyu@xxxxxxxxxx> Cc: Rusty Russell <rusty@xxxxxxxxxxxxxxx> --- include/linux/module.h | 4 ++++ init/main.c | 3 +++ kernel/module.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/linux/module.h b/include/linux/module.h index 21f56393602f..21f7a23f8004 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -257,6 +257,7 @@ extern const typeof(name) __mod_##type##__##name##_device_table \ * files require multiple MODULE_FIRMWARE() specifiers */ #define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware) +struct dwarf_table; struct notifier_block; #ifdef CONFIG_MODULES @@ -393,6 +394,9 @@ struct module { struct module_layout core_layout __module_layout_align; struct module_layout init_layout; + /* The handle returned from dwarf_add_table. */ + struct dwarf_table *dwarf_info; + /* Arch-specific module values */ struct mod_arch_specific arch; diff --git a/init/main.c b/init/main.c index cc48053bb39f..5acedeae355d 100644 --- a/init/main.c +++ b/init/main.c @@ -22,6 +22,7 @@ #include <linux/string.h> #include <linux/ctype.h> #include <linux/delay.h> +#include <linux/dwarf.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/initrd.h> @@ -490,6 +491,7 @@ asmlinkage __visible void __init start_kernel(void) char *command_line; char *after_dashes; + dwarf_init(); set_task_stack_end_magic(&init_task); smp_setup_processor_id(); debug_objects_early_init(); @@ -514,6 +516,7 @@ asmlinkage __visible void __init start_kernel(void) setup_arch(&command_line); mm_init_cpumask(&init_mm); setup_command_line(command_line); + dwarf_setup(); setup_nr_cpu_ids(); setup_per_cpu_areas(); boot_cpu_state_init(); diff --git a/kernel/module.c b/kernel/module.c index 4a3665f8f837..3571328e41fe 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -38,6 +38,7 @@ #include <linux/capability.h> #include <linux/cpu.h> #include <linux/moduleparam.h> +#include <linux/dwarf.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/vermagic.h> @@ -314,7 +315,7 @@ struct load_info { unsigned long mod_kallsyms_init_off; #endif struct { - unsigned int sym, str, mod, vers, info, pcpu; + unsigned int sym, str, mod, vers, info, pcpu, dwarf; } index; }; @@ -753,6 +754,27 @@ bool __is_module_percpu_address(unsigned long addr, unsigned long *can_addr) #endif /* CONFIG_SMP */ +static unsigned int find_dwarf(struct load_info *info) +{ + unsigned int section = 0; +#ifdef ARCH_DWARF_SECTION_NAME + section = find_sec(info, ARCH_DWARF_SECTION_NAME); + if (section) + info->sechdrs[section].sh_flags |= SHF_ALLOC; +#endif + return section; +} + +static void add_dwarf_table(struct module *mod, struct load_info *info) +{ + int index = info->index.dwarf; + + /* Size of section 0 is 0, so this is ok if there is no dwarf info. */ + mod->dwarf_info = dwarf_add_table(mod, + (void *)info->sechdrs[index].sh_addr, + info->sechdrs[index].sh_size); +} + #define MODINFO_ATTR(field) \ static void setup_modinfo_##field(struct module *mod, const char *s) \ { \ @@ -2133,6 +2155,8 @@ static void free_module(struct module *mod) /* Remove dynamic debug info */ ddebug_remove_module(mod->name); + dwarf_remove_table(mod->dwarf_info, false); + /* Arch-specific cleanup. */ module_arch_cleanup(mod); @@ -2970,6 +2994,8 @@ static struct module *setup_load_info(struct load_info *info, int flags) info->index.pcpu = find_pcpusec(info); + info->index.dwarf = find_dwarf(info); + /* Check module struct version now, before we try to use module. */ if (!check_modstruct_version(info->sechdrs, info->index.vers, mod)) return ERR_PTR(-ENOEXEC); @@ -3459,6 +3485,7 @@ static noinline int do_init_module(struct module *mod) /* Drop initial reference. */ module_put(mod); trim_init_extable(mod); + dwarf_remove_table(mod->dwarf_info, true); #ifdef CONFIG_KALLSYMS /* Switch to core kallsyms now init is done: kallsyms may be walking! */ rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms); @@ -3734,6 +3761,9 @@ static int load_module(struct load_info *info, const char __user *uargs, goto sysfs_cleanup; } + /* Initialize dwarf table */ + add_dwarf_table(mod, info); + /* Get rid of temporary copy. */ free_copy(info); -- 2.12.2 -- To unsubscribe from this list: send the line "unsubscribe live-patching" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html