diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 53 | 
1 files changed, 45 insertions, 8 deletions
| diff --git a/kernel/module.c b/kernel/module.c index 927d46cb8eb9..40ec9a030eec 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -13,6 +13,7 @@  #include <linux/trace_events.h>  #include <linux/init.h>  #include <linux/kallsyms.h> +#include <linux/buildid.h>  #include <linux/file.h>  #include <linux/fs.h>  #include <linux/sysfs.h> @@ -1018,8 +1019,7 @@ void __symbol_put(const char *symbol)  	};  	preempt_disable(); -	if (!find_symbol(&fsa)) -		BUG(); +	BUG_ON(!find_symbol(&fsa));  	module_put(fsa.owner);  	preempt_enable();  } @@ -1466,6 +1466,13 @@ resolve_symbol_wait(struct module *mod,  	return ksym;  } +#ifdef CONFIG_KALLSYMS +static inline bool sect_empty(const Elf_Shdr *sect) +{ +	return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; +} +#endif +  /*   * /sys/module/foo/sections stuff   * J. Corbet <corbet@lwn.net> @@ -1473,11 +1480,6 @@ resolve_symbol_wait(struct module *mod,  #ifdef CONFIG_SYSFS  #ifdef CONFIG_KALLSYMS -static inline bool sect_empty(const Elf_Shdr *sect) -{ -	return !(sect->sh_flags & SHF_ALLOC) || sect->sh_size == 0; -} -  struct module_sect_attr {  	struct bin_attribute battr;  	unsigned long address; @@ -2798,6 +2800,26 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)  }  #endif /* CONFIG_KALLSYMS */ +#if IS_ENABLED(CONFIG_KALLSYMS) && IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +static void init_build_id(struct module *mod, const struct load_info *info) +{ +	const Elf_Shdr *sechdr; +	unsigned int i; + +	for (i = 0; i < info->hdr->e_shnum; i++) { +		sechdr = &info->sechdrs[i]; +		if (!sect_empty(sechdr) && sechdr->sh_type == SHT_NOTE && +		    !build_id_parse_buf((void *)sechdr->sh_addr, mod->build_id, +					sechdr->sh_size)) +			break; +	} +} +#else +static void init_build_id(struct module *mod, const struct load_info *info) +{ +} +#endif +  static void dynamic_debug_setup(struct module *mod, struct _ddebug *debug, unsigned int num)  {  	if (!debug) @@ -3333,6 +3355,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)  						sizeof(unsigned long),  						&mod->num_kprobe_blacklist);  #endif +#ifdef CONFIG_PRINTK_INDEX +	mod->printk_index_start = section_objs(info, ".printk_index", +					       sizeof(*mod->printk_index_start), +					       &mod->printk_index_size); +#endif  #ifdef CONFIG_HAVE_STATIC_CALL_INLINE  	mod->static_call_sites = section_objs(info, ".static_call_sites",  					      sizeof(*mod->static_call_sites), @@ -4022,6 +4049,7 @@ static int load_module(struct load_info *info, const char __user *uargs,  		goto free_arch_cleanup;  	} +	init_build_id(mod, info);  	dynamic_debug_setup(mod, info->debug, info->num_debug);  	/* Ftrace init must be called in the MODULE_STATE_UNFORMED state */ @@ -4255,6 +4283,7 @@ const char *module_address_lookup(unsigned long addr,  			    unsigned long *size,  			    unsigned long *offset,  			    char **modname, +			    const unsigned char **modbuildid,  			    char *namebuf)  {  	const char *ret = NULL; @@ -4265,6 +4294,13 @@ const char *module_address_lookup(unsigned long addr,  	if (mod) {  		if (modname)  			*modname = mod->name; +		if (modbuildid) { +#if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) +			*modbuildid = mod->build_id; +#else +			*modbuildid = NULL; +#endif +		}  		ret = find_kallsyms_symbol(mod, addr, size, offset);  	} @@ -4425,9 +4461,10 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,  			ret = fn(data, kallsyms_symbol_name(kallsyms, i),  				 mod, kallsyms_symbol_value(sym));  			if (ret != 0) -				break; +				goto out;  		}  	} +out:  	mutex_unlock(&module_mutex);  	return ret;  } | 
