Commit 4a4962263f07d14660849ec134ee42b63e95ea9a
Committed by
Rusty Russell
1 parent
94a8d5caba
Exists in
master
and in
4 other branches
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 */ |
kernel/module.c
... | ... | @@ -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; |