Commit 4a4962263f07d14660849ec134ee42b63e95ea9a

Authored by Jan Beulich
Committed by Rusty Russell
1 parent 94a8d5caba

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>

Showing 2 changed files with 94 additions and 7 deletions Side-by-side Diff

include/linux/module.h
... ... @@ -308,9 +308,13 @@
308 308 #endif
309 309  
310 310 #ifdef CONFIG_KALLSYMS
311   - /* We keep the symbol and string tables for kallsyms. */
312   - Elf_Sym *symtab;
313   - unsigned int num_symtab;
  311 + /*
  312 + * We keep the symbol and string tables for kallsyms.
  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 318 char *strtab;
315 319  
316 320 /* Section attributes */
... ... @@ -1862,13 +1862,68 @@
1862 1862 return '?';
1863 1863 }
1864 1864  
  1865 +static 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 +
  1886 +static 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 +
1865 1916 static void add_kallsyms(struct module *mod,
1866 1917 Elf_Shdr *sechdrs,
  1918 + unsigned int shnum,
1867 1919 unsigned int symindex,
1868 1920 unsigned int strindex,
  1921 + unsigned long symoffs,
1869 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 1928 mod->symtab = (void *)sechdrs[symindex].sh_addr;
1874 1929 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
1875 1930  
1876 1931  
1877 1932  
... ... @@ -1878,12 +1933,32 @@
1878 1933 for (i = 0; i < mod->num_symtab; i++)
1879 1934 mod->symtab[i].st_info
1880 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 1948 #else
  1949 +static 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 +}
1883 1956 static inline void add_kallsyms(struct module *mod,
1884 1957 Elf_Shdr *sechdrs,
  1958 + unsigned int shnum,
1885 1959 unsigned int symindex,
1886 1960 unsigned int strindex,
  1961 + unsigned long symoffs,
1887 1962 const char *secstrings)
1888 1963 {
1889 1964 }
... ... @@ -1959,6 +2034,9 @@
1959 2034 struct module *mod;
1960 2035 long err = 0;
1961 2036 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
  2037 +#ifdef CONFIG_KALLSYMS
  2038 + unsigned long symoffs;
  2039 +#endif
1962 2040 mm_segment_t old_fs;
1963 2041  
1964 2042 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
... ... @@ -2041,8 +2119,7 @@
2041 2119 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2042 2120 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2043 2121 #ifdef CONFIG_KALLSYMS
2044   - /* Keep symbol and string tables for decoding later. */
2045   - sechdrs[symindex].sh_flags |= SHF_ALLOC;
  2122 + /* Keep string table for decoding later. */
2046 2123 sechdrs[strindex].sh_flags |= SHF_ALLOC;
2047 2124 #endif
2048 2125  
... ... @@ -2109,6 +2186,7 @@
2109 2186 this is done generically; there doesn't appear to be any
2110 2187 special cases for the architectures. */
2111 2188 layout_sections(mod, hdr, sechdrs, secstrings);
  2189 + symoffs = layout_symtab(mod, sechdrs, symindex, hdr, secstrings);
2112 2190  
2113 2191 /* Do the allocs. */
2114 2192 ptr = module_alloc_update_bounds(mod->core_size);
... ... @@ -2313,7 +2391,8 @@
2313 2391 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
2314 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 2397 if (!mod->taints) {
2319 2398 struct _ddebug *debug;
... ... @@ -2491,6 +2570,10 @@
2491 2570 /* Drop initial reference. */
2492 2571 module_put(mod);
2493 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 2577 module_free(mod, mod->module_init);
2495 2578 mod->module_init = NULL;
2496 2579 mod->init_size = 0;