[PATCH] also discard .*init sections after module initialization

From: Jan Beulich
Date: Tue Jun 30 2009 - 07:57:39 EST


Just like .init, these sections are supposed to be unneeded after init,
and modpost warns about improper section references anyway. Likewise
for .*exit which, other than .exit, aren't needed for the module unload
path.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

---
arch/ia64/kernel/module.c | 3 ++-
arch/powerpc/kernel/module_32.c | 14 ++++++++------
arch/powerpc/kernel/module_64.c | 5 ++---
include/linux/module.h | 2 ++
kernel/module.c | 37 +++++++++++++++++++++++++++++++++++--
5 files changed, 49 insertions(+), 12 deletions(-)

--- linux-2.6.31-rc1/arch/ia64/kernel/module.c 2009-06-26 17:49:37.000000000 +0200
+++ 2.6.31-rc1-module-discard-xxxinit/arch/ia64/kernel/module.c 2009-04-27 12:06:09.000000000 +0200
@@ -473,7 +473,8 @@ module_frob_arch_sections (Elf_Ehdr *ehd

gots += count_gots(rels, numrels);
fdescs += count_fdescs(rels, numrels);
- if (strstr(secstrings + s->sh_name, ".init"))
+ if (is_init_section_name(secstrings
+ + sechdrs[s->sh_info].sh_name))
init_plts += count_plts(rels, numrels);
else
core_plts += count_plts(rels, numrels);
--- linux-2.6.31-rc1/arch/powerpc/kernel/module_32.c 2009-03-24 00:12:14.000000000 +0100
+++ 2.6.31-rc1-module-discard-xxxinit/arch/powerpc/kernel/module_32.c 2009-04-27 12:06:09.000000000 +0200
@@ -111,17 +111,19 @@ static unsigned long get_plt_size(const
/* Everything marked ALLOC (this includes the exported
symbols) */
for (i = 1; i < hdr->e_shnum; i++) {
- /* If it's called *.init*, and we're not init, we're
- not interested */
- if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
- != is_init)
- continue;
-
/* We don't want to look at debug sections. */
if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0)
continue;

if (sechdrs[i].sh_type == SHT_RELA) {
+ /* If it's .init-like, and we're not init, we're
+ not interested */
+ if (is_init_section_name(secstrings
+ + sechdrs[sechdrs[i].sh_info]
+ .sh_name)
+ != is_init)
+ continue;
+
DEBUGP("Found relocations in section %u\n", i);
DEBUGP("Ptr: %p. Number: %u\n",
(void *)hdr + sechdrs[i].sh_offset,
--- linux-2.6.31-rc1/arch/powerpc/kernel/module_64.c 2009-06-10 05:05:27.000000000 +0200
+++ 2.6.31-rc1-module-discard-xxxinit/arch/powerpc/kernel/module_64.c 2009-04-27 12:06:09.000000000 +0200
@@ -206,7 +206,6 @@ int module_frob_arch_sections(Elf64_Ehdr

/* Find .toc and .stubs sections, symtab and strtab */
for (i = 1; i < hdr->e_shnum; i++) {
- char *p;
if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0)
me->arch.stubs_section = i;
else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0)
@@ -216,8 +215,8 @@ int module_frob_arch_sections(Elf64_Ehdr
sechdrs[i].sh_size);

/* We don't handle .init for the moment: rename to _init */
- while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init")))
- p[0] = '_';
+ if (is_init_section_name(secstrings + sechdrs[i].sh_name))
+ secstrings[sechdrs[i].sh_name] = '_';

if (sechdrs[i].sh_type == SHT_SYMTAB)
dedotify((void *)hdr + sechdrs[i].sh_offset,
--- linux-2.6.31-rc1/include/linux/module.h 2009-06-26 17:50:00.000000000 +0200
+++ 2.6.31-rc1-module-discard-xxxinit/include/linux/module.h 2009-04-27 12:07:17.000000000 +0200
@@ -401,6 +401,8 @@ static inline int within_module_init(uns
addr < (unsigned long)mod->module_init + mod->init_size;
}

+bool is_init_section_name(const char *);
+
/* Search for module by name: must hold module_mutex. */
struct module *find_module(const char *name);

--- linux-2.6.31-rc1/kernel/module.c 2009-06-26 17:50:00.000000000 +0200
+++ 2.6.31-rc1-module-discard-xxxinit/kernel/module.c 2009-04-27 12:11:51.000000000 +0200
@@ -1655,6 +1655,39 @@ static long get_offset(struct module *mo
return ret;
}

+bool is_init_section_name(const char *name)
+{
+ unsigned int i, n;
+ static const char *const prefixes[] = {
+#ifndef CONFIG_HOTPLUG_CPU
+ "cpu",
+#endif
+#ifndef CONFIG_HOTPLUG
+ "dev",
+#endif
+#ifndef CONFIG_MEMORY_HOTPLUG
+ "mem",
+#endif
+ ""
+ };
+
+ if (*name++ != '.')
+ return false;
+ for (i = 0; i < ARRAY_SIZE(prefixes); ++i) {
+ n = strlen(prefixes[i]);
+ if (strncmp(name, prefixes[i], n) == 0)
+ break;
+ }
+ if (i >= ARRAY_SIZE(prefixes))
+ return false;
+#ifdef CONFIG_MODULE_UNLOAD
+ if (n == 0 && strncmp(name, "exit", 4) == 0)
+ return false;
+#endif
+ return strncmp(name + n, "init", 4) == 0
+ || strncmp(name + n, "exit", 4) == 0;
+}
+
/* Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
might -- code, read-only data, read-write data, small data. Tally
sizes, and place the offsets into sh_entsize fields: high bit means it
@@ -1686,7 +1719,7 @@ static void layout_sections(struct modul
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL
- || strstarts(secstrings + s->sh_name, ".init"))
+ || is_init_section_name(secstrings + s->sh_name))
continue;
s->sh_entsize = get_offset(mod, &mod->core_size, s, i);
DEBUGP("\t%s\n", secstrings + s->sh_name);
@@ -1703,7 +1736,7 @@ static void layout_sections(struct modul
if ((s->sh_flags & masks[m][0]) != masks[m][0]
|| (s->sh_flags & masks[m][1])
|| s->sh_entsize != ~0UL
- || !strstarts(secstrings + s->sh_name, ".init"))
+ || !is_init_section_name(secstrings + s->sh_name))
continue;
s->sh_entsize = (get_offset(mod, &mod->init_size, s, i)
| INIT_OFFSET_MASK);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/