aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2004-06-21 01:14:21 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2004-06-21 01:14:21 -0700
commit269986dcf4017c4bd44aa1f81d3b94349ca93296 (patch)
tree96a0a74ae12f39af1a7f5e2062dea3e8987f28ee /kernel
parent9a85e04ec3e527234d8a2210e6ba04d7af9a4298 (diff)
parentc4a9c8212b8e954da29dc2e9002842729c0ba6d1 (diff)
downloadhistory-269986dcf4017c4bd44aa1f81d3b94349ca93296.tar.gz
merge
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c100
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);