aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2004-06-08 20:19:23 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2004-06-08 20:19:23 -0700
commit8d3c4ddbe90dabe046eea65af18e944aa5f233c9 (patch)
treed3373452b465d547c61d89feff09ec50e5a63945 /kernel
parenta85f1c6a19be3febbf35eeb7bd70968e05158062 (diff)
parentfce72d4bb592da5890d2b83dd22d6e4a5f46c7e0 (diff)
downloadhistory-8d3c4ddbe90dabe046eea65af18e944aa5f233c9.tar.gz
merge i2c-2.6 into driver-2.6 trees due to problems people reported.
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 e7a73bac2d58a4..08b14bc7b299df 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -981,6 +981,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,
@@ -1099,6 +1197,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. */
@@ -1712,6 +1811,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);