aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@novell.com>2009-07-06 09:50:42 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-09-24 11:02:57 -0400
commit4a4962263f07d14660849ec134ee42b63e95ea9a (patch)
tree0edfe694167c224a6d9e48901743edd478a71c29
parent94a8d5caba74211ec76dac80fc6e2d5c391530df (diff)
module: reduce symbol table for loaded modules (v2)
Discard all symbols not interesting for kallsyms use: absolute, section, and in the common case (!KALLSYMS_ALL) data ones. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--include/linux/module.h10
-rw-r--r--kernel/module.c91
2 files changed, 94 insertions, 7 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 1c755b2f937d..1d3ccb173fd6 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -308,9 +308,13 @@ struct module
308#endif 308#endif
309 309
310#ifdef CONFIG_KALLSYMS 310#ifdef CONFIG_KALLSYMS
311 /* We keep the symbol and string tables for kallsyms. */ 311 /*
312 Elf_Sym *symtab; 312 * We keep the symbol and string tables for kallsyms.
313 unsigned int num_symtab; 313 * The core_* fields below are temporary, loader-only (they
314 * could really be discarded after module init).
315 */
316 Elf_Sym *symtab, *core_symtab;
317 unsigned int num_symtab, core_num_syms;
314 char *strtab; 318 char *strtab;
315 319
316 /* Section attributes */ 320 /* Section attributes */
diff --git a/kernel/module.c b/kernel/module.c
index e6bc4b28aa62..97f4d5e15535 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1862,13 +1862,68 @@ static char elf_type(const Elf_Sym *sym,
1862 return '?'; 1862 return '?';
1863} 1863}
1864 1864
1865static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
1866 unsigned int shnum)
1867{
1868 const Elf_Shdr *sec;
1869
1870 if (src->st_shndx == SHN_UNDEF
1871 || src->st_shndx >= shnum
1872 || !src->st_name)
1873 return false;
1874
1875 sec = sechdrs + src->st_shndx;
1876 if (!(sec->sh_flags & SHF_ALLOC)
1877#ifndef CONFIG_KALLSYMS_ALL
1878 || !(sec->sh_flags & SHF_EXECINSTR)
1879#endif
1880 || (sec->sh_entsize & INIT_OFFSET_MASK))
1881 return false;
1882
1883 return true;
1884}
1885
1886static unsigned long layout_symtab(struct module *mod,
1887 Elf_Shdr *sechdrs,
1888 unsigned int symindex,
1889 const Elf_Ehdr *hdr,
1890 const char *secstrings)
1891{
1892 unsigned long symoffs;
1893 Elf_Shdr *symsect = sechdrs + symindex;
1894 const Elf_Sym *src;
1895 unsigned int i, nsrc, ndst;
1896
1897 /* Put symbol section at end of init part of module. */
1898 symsect->sh_flags |= SHF_ALLOC;
1899 symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect,
1900 symindex) | INIT_OFFSET_MASK;
1901 DEBUGP("\t%s\n", secstrings + symsect->sh_name);
1902
1903 src = (void *)hdr + symsect->sh_offset;
1904 nsrc = symsect->sh_size / sizeof(*src);
1905 for (ndst = i = 1; i < nsrc; ++i, ++src)
1906 if (is_core_symbol(src, sechdrs, hdr->e_shnum))
1907 ++ndst;
1908
1909 /* Append room for core symbols at end of core part. */
1910 symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
1911 mod->core_size = symoffs + ndst * sizeof(Elf_Sym);
1912
1913 return symoffs;
1914}
1915
1865static void add_kallsyms(struct module *mod, 1916static void add_kallsyms(struct module *mod,
1866 Elf_Shdr *sechdrs, 1917 Elf_Shdr *sechdrs,
1918 unsigned int shnum,
1867 unsigned int symindex, 1919 unsigned int symindex,
1868 unsigned int strindex, 1920 unsigned int strindex,
1921 unsigned long symoffs,
1869 const char *secstrings) 1922 const char *secstrings)
1870{ 1923{
1871 unsigned int i; 1924 unsigned int i, ndst;
1925 const Elf_Sym *src;
1926 Elf_Sym *dst;
1872 1927
1873 mod->symtab = (void *)sechdrs[symindex].sh_addr; 1928 mod->symtab = (void *)sechdrs[symindex].sh_addr;
1874 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); 1929 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
@@ -1878,12 +1933,32 @@ static void add_kallsyms(struct module *mod,
1878 for (i = 0; i < mod->num_symtab; i++) 1933 for (i = 0; i < mod->num_symtab; i++)
1879 mod->symtab[i].st_info 1934 mod->symtab[i].st_info
1880 = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); 1935 = elf_type(&mod->symtab[i], sechdrs, secstrings, mod);
1936
1937 mod->core_symtab = dst = mod->module_core + symoffs;
1938 src = mod->symtab;
1939 *dst = *src;
1940 for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
1941 if (!is_core_symbol(src, sechdrs, shnum))
1942 continue;
1943 dst[ndst] = *src;
1944 ++ndst;
1945 }
1946 mod->core_num_syms = ndst;
1881} 1947}
1882#else 1948#else
1949static inline unsigned long layout_symtab(struct module *mod,
1950 Elf_Shdr *sechdrs,
1951 unsigned int symindex,
1952 const Elf_Hdr *hdr,
1953 const char *secstrings)
1954{
1955}
1883static inline void add_kallsyms(struct module *mod, 1956static inline void add_kallsyms(struct module *mod,
1884 Elf_Shdr *sechdrs, 1957 Elf_Shdr *sechdrs,
1958 unsigned int shnum,
1885 unsigned int symindex, 1959 unsigned int symindex,
1886 unsigned int strindex, 1960 unsigned int strindex,
1961 unsigned long symoffs,
1887 const char *secstrings) 1962 const char *secstrings)
1888{ 1963{
1889} 1964}
@@ -1959,6 +2034,9 @@ static noinline struct module *load_module(void __user *umod,
1959 struct module *mod; 2034 struct module *mod;
1960 long err = 0; 2035 long err = 0;
1961 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 2036 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
2037#ifdef CONFIG_KALLSYMS
2038 unsigned long symoffs;
2039#endif
1962 mm_segment_t old_fs; 2040 mm_segment_t old_fs;
1963 2041
1964 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 2042 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -2041,8 +2119,7 @@ static noinline struct module *load_module(void __user *umod,
2041 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2119 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2042 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2120 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2043#ifdef CONFIG_KALLSYMS 2121#ifdef CONFIG_KALLSYMS
2044 /* Keep symbol and string tables for decoding later. */ 2122 /* Keep string table for decoding later. */
2045 sechdrs[symindex].sh_flags |= SHF_ALLOC;
2046 sechdrs[strindex].sh_flags |= SHF_ALLOC; 2123 sechdrs[strindex].sh_flags |= SHF_ALLOC;
2047#endif 2124#endif
2048 2125
@@ -2109,6 +2186,7 @@ static noinline struct module *load_module(void __user *umod,
2109 this is done generically; there doesn't appear to be any 2186 this is done generically; there doesn't appear to be any
2110 special cases for the architectures. */ 2187 special cases for the architectures. */
2111 layout_sections(mod, hdr, sechdrs, secstrings); 2188 layout_sections(mod, hdr, sechdrs, secstrings);
2189 symoffs = layout_symtab(mod, sechdrs, symindex, hdr, secstrings);
2112 2190
2113 /* Do the allocs. */ 2191 /* Do the allocs. */
2114 ptr = module_alloc_update_bounds(mod->core_size); 2192 ptr = module_alloc_update_bounds(mod->core_size);
@@ -2313,7 +2391,8 @@ static noinline struct module *load_module(void __user *umod,
2313 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, 2391 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
2314 sechdrs[pcpuindex].sh_size); 2392 sechdrs[pcpuindex].sh_size);
2315 2393
2316 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); 2394 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
2395 symoffs, secstrings);
2317 2396
2318 if (!mod->taints) { 2397 if (!mod->taints) {
2319 struct _ddebug *debug; 2398 struct _ddebug *debug;
@@ -2491,6 +2570,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
2491 /* Drop initial reference. */ 2570 /* Drop initial reference. */
2492 module_put(mod); 2571 module_put(mod);
2493 trim_init_extable(mod); 2572 trim_init_extable(mod);
2573#ifdef CONFIG_KALLSYMS
2574 mod->num_symtab = mod->core_num_syms;
2575 mod->symtab = mod->core_symtab;
2576#endif
2494 module_free(mod, mod->module_init); 2577 module_free(mod, mod->module_init);
2495 mod->module_init = NULL; 2578 mod->module_init = NULL;
2496 mod->init_size = 0; 2579 mod->init_size = 0;