diff options
author | Greg Kroah-Hartman <greg@kroah.com> | 2004-06-21 01:14:21 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <greg@kroah.com> | 2004-06-21 01:14:21 -0700 |
commit | 269986dcf4017c4bd44aa1f81d3b94349ca93296 (patch) | |
tree | 96a0a74ae12f39af1a7f5e2062dea3e8987f28ee /kernel | |
parent | 9a85e04ec3e527234d8a2210e6ba04d7af9a4298 (diff) | |
parent | c4a9c8212b8e954da29dc2e9002842729c0ba6d1 (diff) | |
download | history-269986dcf4017c4bd44aa1f81d3b94349ca93296.tar.gz |
merge
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/kernel/module.c b/kernel/module.c index b96b1397422b8d..71a0944bddb1cf 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -980,6 +980,104 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, return ret; } + +/* + * /sys/module/foo/sections stuff + * J. Corbet <corbet@lwn.net> + */ +#ifdef CONFIG_KALLSYMS +static void module_sect_attrs_release(struct kobject *kobj) +{ + kfree(container_of(kobj, struct module_sections, kobj)); +} + +static ssize_t module_sect_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct module_sect_attr *sattr = + container_of(attr, struct module_sect_attr, attr); + return sprintf(buf, "0x%lx\n", sattr->address); +} + +static struct sysfs_ops module_sect_ops = { + .show = module_sect_show, +}; + +static struct kobj_type module_sect_ktype = { + .sysfs_ops = &module_sect_ops, + .release = module_sect_attrs_release, +}; + +static void add_sect_attrs(struct module *mod, unsigned int nsect, + char *secstrings, Elf_Shdr *sechdrs) +{ + unsigned int nloaded = 0, i; + struct module_sect_attr *sattr; + + if (!mod->mkobj) + return; + + /* Count loaded sections and allocate structures */ + for (i = 0; i < nsect; i++) + if (sechdrs[i].sh_flags & SHF_ALLOC) + nloaded++; + mod->sect_attrs = kmalloc(sizeof(struct module_sections) + + nloaded*sizeof(mod->sect_attrs->attrs[0]), GFP_KERNEL); + if (! mod->sect_attrs) + return; + + /* sections entry setup */ + memset(mod->sect_attrs, 0, sizeof(struct module_sections)); + if (kobject_set_name(&mod->sect_attrs->kobj, "sections")) + goto out; + mod->sect_attrs->kobj.parent = &mod->mkobj->kobj; + mod->sect_attrs->kobj.ktype = &module_sect_ktype; + if (kobject_register(&mod->sect_attrs->kobj)) + goto out; + + /* And the section attributes. */ + sattr = &mod->sect_attrs->attrs[0]; + for (i = 0; i < nsect; i++) { + if (! (sechdrs[i].sh_flags & SHF_ALLOC)) + continue; + sattr->address = sechdrs[i].sh_addr; + strlcpy(sattr->name, secstrings + sechdrs[i].sh_name, + MODULE_SECT_NAME_LEN); + sattr->attr.name = sattr->name; + sattr->attr.owner = mod; + sattr->attr.mode = S_IRUGO; + (void) sysfs_create_file(&mod->sect_attrs->kobj, &sattr->attr); + sattr++; + } + return; + out: + kfree(mod->sect_attrs); + mod->sect_attrs = NULL; +} + +static void remove_sect_attrs(struct module *mod) +{ + if (mod->sect_attrs) { + kobject_unregister(&mod->sect_attrs->kobj); + mod->sect_attrs = NULL; + } +} + + +#else +static inline void add_sect_attrs(struct module *mod, unsigned int nsect, + char *sectstrings, Elf_Shdr *sechdrs) +{ +} + +static inline void remove_sect_attrs(struct module *mod) +{ +} +#endif /* CONFIG_KALLSYMS */ + + + + #define to_module_attr(n) container_of(n, struct module_attribute, attr); static ssize_t module_attr_show(struct kobject *kobj, @@ -1098,6 +1196,7 @@ static void free_module(struct module *mod) list_del(&mod->list); spin_unlock_irq(&modlist_lock); + remove_sect_attrs(mod); mod_kobject_remove(mod); /* Arch-specific cleanup. */ @@ -1711,6 +1810,7 @@ static struct module *load_module(void __user *umod, / sizeof(struct kernel_param)); if (err < 0) goto arch_cleanup; + add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); /* Get rid of temporary copy */ vfree(hdr); |