aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@novell.com>2009-07-06 09:51:44 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-09-24 11:02:57 -0400
commit554bdfe5acf3715e87c8d5e25a4f9a896ac9f014 (patch)
tree8a03f9799114c8100a3e54d230d9e31703248f7a /kernel/module.c
parent4a4962263f07d14660849ec134ee42b63e95ea9a (diff)
module: reduce string table for loaded modules (v2)
Also remove all parts of the string table (referenced by the symbol table) that are not needed for kallsyms use (i.e. which were only referenced by symbols discarded by the previous patch, or not referenced at all for whatever reason). Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c68
1 files changed, 56 insertions, 12 deletions
diff --git a/kernel/module.c b/kernel/module.c
index 97f4d5e15535..39827c3d9484 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1886,12 +1886,17 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
1886static unsigned long layout_symtab(struct module *mod, 1886static unsigned long layout_symtab(struct module *mod,
1887 Elf_Shdr *sechdrs, 1887 Elf_Shdr *sechdrs,
1888 unsigned int symindex, 1888 unsigned int symindex,
1889 unsigned int strindex,
1889 const Elf_Ehdr *hdr, 1890 const Elf_Ehdr *hdr,
1890 const char *secstrings) 1891 const char *secstrings,
1892 unsigned long *pstroffs,
1893 unsigned long *strmap)
1891{ 1894{
1892 unsigned long symoffs; 1895 unsigned long symoffs;
1893 Elf_Shdr *symsect = sechdrs + symindex; 1896 Elf_Shdr *symsect = sechdrs + symindex;
1897 Elf_Shdr *strsect = sechdrs + strindex;
1894 const Elf_Sym *src; 1898 const Elf_Sym *src;
1899 const char *strtab;
1895 unsigned int i, nsrc, ndst; 1900 unsigned int i, nsrc, ndst;
1896 1901
1897 /* Put symbol section at end of init part of module. */ 1902 /* Put symbol section at end of init part of module. */
@@ -1902,14 +1907,31 @@ static unsigned long layout_symtab(struct module *mod,
1902 1907
1903 src = (void *)hdr + symsect->sh_offset; 1908 src = (void *)hdr + symsect->sh_offset;
1904 nsrc = symsect->sh_size / sizeof(*src); 1909 nsrc = symsect->sh_size / sizeof(*src);
1910 strtab = (void *)hdr + strsect->sh_offset;
1905 for (ndst = i = 1; i < nsrc; ++i, ++src) 1911 for (ndst = i = 1; i < nsrc; ++i, ++src)
1906 if (is_core_symbol(src, sechdrs, hdr->e_shnum)) 1912 if (is_core_symbol(src, sechdrs, hdr->e_shnum)) {
1913 unsigned int j = src->st_name;
1914
1915 while(!__test_and_set_bit(j, strmap) && strtab[j])
1916 ++j;
1907 ++ndst; 1917 ++ndst;
1918 }
1908 1919
1909 /* Append room for core symbols at end of core part. */ 1920 /* Append room for core symbols at end of core part. */
1910 symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); 1921 symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
1911 mod->core_size = symoffs + ndst * sizeof(Elf_Sym); 1922 mod->core_size = symoffs + ndst * sizeof(Elf_Sym);
1912 1923
1924 /* Put string table section at end of init part of module. */
1925 strsect->sh_flags |= SHF_ALLOC;
1926 strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
1927 strindex) | INIT_OFFSET_MASK;
1928 DEBUGP("\t%s\n", secstrings + strsect->sh_name);
1929
1930 /* Append room for core symbols' strings at end of core part. */
1931 *pstroffs = mod->core_size;
1932 __set_bit(0, strmap);
1933 mod->core_size += bitmap_weight(strmap, strsect->sh_size);
1934
1913 return symoffs; 1935 return symoffs;
1914} 1936}
1915 1937
@@ -1919,11 +1941,14 @@ static void add_kallsyms(struct module *mod,
1919 unsigned int symindex, 1941 unsigned int symindex,
1920 unsigned int strindex, 1942 unsigned int strindex,
1921 unsigned long symoffs, 1943 unsigned long symoffs,
1922 const char *secstrings) 1944 unsigned long stroffs,
1945 const char *secstrings,
1946 unsigned long *strmap)
1923{ 1947{
1924 unsigned int i, ndst; 1948 unsigned int i, ndst;
1925 const Elf_Sym *src; 1949 const Elf_Sym *src;
1926 Elf_Sym *dst; 1950 Elf_Sym *dst;
1951 char *s;
1927 1952
1928 mod->symtab = (void *)sechdrs[symindex].sh_addr; 1953 mod->symtab = (void *)sechdrs[symindex].sh_addr;
1929 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); 1954 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
@@ -1941,16 +1966,25 @@ static void add_kallsyms(struct module *mod,
1941 if (!is_core_symbol(src, sechdrs, shnum)) 1966 if (!is_core_symbol(src, sechdrs, shnum))
1942 continue; 1967 continue;
1943 dst[ndst] = *src; 1968 dst[ndst] = *src;
1969 dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name);
1944 ++ndst; 1970 ++ndst;
1945 } 1971 }
1946 mod->core_num_syms = ndst; 1972 mod->core_num_syms = ndst;
1973
1974 mod->core_strtab = s = mod->module_core + stroffs;
1975 for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i)
1976 if (test_bit(i, strmap))
1977 *++s = mod->strtab[i];
1947} 1978}
1948#else 1979#else
1949static inline unsigned long layout_symtab(struct module *mod, 1980static inline unsigned long layout_symtab(struct module *mod,
1950 Elf_Shdr *sechdrs, 1981 Elf_Shdr *sechdrs,
1951 unsigned int symindex, 1982 unsigned int symindex,
1983 unsigned int strindex,
1952 const Elf_Hdr *hdr, 1984 const Elf_Hdr *hdr,
1953 const char *secstrings) 1985 const char *secstrings,
1986 unsigned long *pstroffs,
1987 unsigned long *strmap)
1954{ 1988{
1955} 1989}
1956static inline void add_kallsyms(struct module *mod, 1990static inline void add_kallsyms(struct module *mod,
@@ -1959,7 +1993,9 @@ static inline void add_kallsyms(struct module *mod,
1959 unsigned int symindex, 1993 unsigned int symindex,
1960 unsigned int strindex, 1994 unsigned int strindex,
1961 unsigned long symoffs, 1995 unsigned long symoffs,
1962 const char *secstrings) 1996 unsigned long stroffs,
1997 const char *secstrings,
1998 const unsigned long *strmap)
1963{ 1999{
1964} 2000}
1965#endif /* CONFIG_KALLSYMS */ 2001#endif /* CONFIG_KALLSYMS */
@@ -2035,7 +2071,7 @@ static noinline struct module *load_module(void __user *umod,
2035 long err = 0; 2071 long err = 0;
2036 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 2072 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
2037#ifdef CONFIG_KALLSYMS 2073#ifdef CONFIG_KALLSYMS
2038 unsigned long symoffs; 2074 unsigned long symoffs, stroffs, *strmap;
2039#endif 2075#endif
2040 mm_segment_t old_fs; 2076 mm_segment_t old_fs;
2041 2077
@@ -2118,10 +2154,6 @@ static noinline struct module *load_module(void __user *umod,
2118 /* Don't keep modinfo and version sections. */ 2154 /* Don't keep modinfo and version sections. */
2119 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2155 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2120 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2156 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2121#ifdef CONFIG_KALLSYMS
2122 /* Keep string table for decoding later. */
2123 sechdrs[strindex].sh_flags |= SHF_ALLOC;
2124#endif
2125 2157
2126 /* Check module struct version now, before we try to use module. */ 2158 /* Check module struct version now, before we try to use module. */
2127 if (!check_modstruct_version(sechdrs, versindex, mod)) { 2159 if (!check_modstruct_version(sechdrs, versindex, mod)) {
@@ -2157,6 +2189,13 @@ static noinline struct module *load_module(void __user *umod,
2157 goto free_hdr; 2189 goto free_hdr;
2158 } 2190 }
2159 2191
2192 strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size)
2193 * sizeof(long), GFP_KERNEL);
2194 if (!strmap) {
2195 err = -ENOMEM;
2196 goto free_mod;
2197 }
2198
2160 if (find_module(mod->name)) { 2199 if (find_module(mod->name)) {
2161 err = -EEXIST; 2200 err = -EEXIST;
2162 goto free_mod; 2201 goto free_mod;
@@ -2186,7 +2225,8 @@ static noinline struct module *load_module(void __user *umod,
2186 this is done generically; there doesn't appear to be any 2225 this is done generically; there doesn't appear to be any
2187 special cases for the architectures. */ 2226 special cases for the architectures. */
2188 layout_sections(mod, hdr, sechdrs, secstrings); 2227 layout_sections(mod, hdr, sechdrs, secstrings);
2189 symoffs = layout_symtab(mod, sechdrs, symindex, hdr, secstrings); 2228 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr,
2229 secstrings, &stroffs, strmap);
2190 2230
2191 /* Do the allocs. */ 2231 /* Do the allocs. */
2192 ptr = module_alloc_update_bounds(mod->core_size); 2232 ptr = module_alloc_update_bounds(mod->core_size);
@@ -2392,7 +2432,9 @@ static noinline struct module *load_module(void __user *umod,
2392 sechdrs[pcpuindex].sh_size); 2432 sechdrs[pcpuindex].sh_size);
2393 2433
2394 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, 2434 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
2395 symoffs, secstrings); 2435 symoffs, stroffs, secstrings, strmap);
2436 kfree(strmap);
2437 strmap = NULL;
2396 2438
2397 if (!mod->taints) { 2439 if (!mod->taints) {
2398 struct _ddebug *debug; 2440 struct _ddebug *debug;
@@ -2481,6 +2523,7 @@ static noinline struct module *load_module(void __user *umod,
2481 percpu_modfree(percpu); 2523 percpu_modfree(percpu);
2482 free_mod: 2524 free_mod:
2483 kfree(args); 2525 kfree(args);
2526 kfree(strmap);
2484 free_hdr: 2527 free_hdr:
2485 vfree(hdr); 2528 vfree(hdr);
2486 return ERR_PTR(err); 2529 return ERR_PTR(err);
@@ -2573,6 +2616,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
2573#ifdef CONFIG_KALLSYMS 2616#ifdef CONFIG_KALLSYMS
2574 mod->num_symtab = mod->core_num_syms; 2617 mod->num_symtab = mod->core_num_syms;
2575 mod->symtab = mod->core_symtab; 2618 mod->symtab = mod->core_symtab;
2619 mod->strtab = mod->core_strtab;
2576#endif 2620#endif
2577 module_free(mod, mod->module_init); 2621 module_free(mod, mod->module_init);
2578 mod->module_init = NULL; 2622 mod->module_init = NULL;