aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c65
1 files changed, 21 insertions, 44 deletions
diff --git a/kernel/module.c b/kernel/module.c
index cf9f1b6b3268..4928cffc3dcc 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -138,7 +138,6 @@ struct load_info {
138 unsigned long len; 138 unsigned long len;
139 Elf_Shdr *sechdrs; 139 Elf_Shdr *sechdrs;
140 char *secstrings, *strtab; 140 char *secstrings, *strtab;
141 unsigned long *strmap;
142 unsigned long symoffs, stroffs; 141 unsigned long symoffs, stroffs;
143 struct _ddebug *debug; 142 struct _ddebug *debug;
144 unsigned int num_debug; 143 unsigned int num_debug;
@@ -2178,12 +2177,19 @@ static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
2178 return true; 2177 return true;
2179} 2178}
2180 2179
2180/*
2181 * We only allocate and copy the strings needed by the parts of symtab
2182 * we keep. This is simple, but has the effect of making multiple
2183 * copies of duplicates. We could be more sophisticated, see
2184 * linux-kernel thread starting with
2185 * <73defb5e4bca04a6431392cc341112b1@localhost>.
2186 */
2181static void layout_symtab(struct module *mod, struct load_info *info) 2187static void layout_symtab(struct module *mod, struct load_info *info)
2182{ 2188{
2183 Elf_Shdr *symsect = info->sechdrs + info->index.sym; 2189 Elf_Shdr *symsect = info->sechdrs + info->index.sym;
2184 Elf_Shdr *strsect = info->sechdrs + info->index.str; 2190 Elf_Shdr *strsect = info->sechdrs + info->index.str;
2185 const Elf_Sym *src; 2191 const Elf_Sym *src;
2186 unsigned int i, nsrc, ndst; 2192 unsigned int i, nsrc, ndst, strtab_size;
2187 2193
2188 /* Put symbol section at end of init part of module. */ 2194 /* Put symbol section at end of init part of module. */
2189 symsect->sh_flags |= SHF_ALLOC; 2195 symsect->sh_flags |= SHF_ALLOC;
@@ -2194,38 +2200,23 @@ static void layout_symtab(struct module *mod, struct load_info *info)
2194 src = (void *)info->hdr + symsect->sh_offset; 2200 src = (void *)info->hdr + symsect->sh_offset;
2195 nsrc = symsect->sh_size / sizeof(*src); 2201 nsrc = symsect->sh_size / sizeof(*src);
2196 2202
2197 /* 2203 /* Compute total space required for the core symbols' strtab. */
2198 * info->strmap has a '1' bit for each byte of .strtab we want to 2204 for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
2199 * keep resident in mod->core_strtab. Everything else in .strtab
2200 * is unreferenced by the symbols in mod->core_symtab, and will be
2201 * discarded when add_kallsyms() compacts the string table.
2202 */
2203 for (ndst = i = 1; i < nsrc; ++i, ++src)
2204 if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { 2205 if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
2205 unsigned int j = src->st_name; 2206 strtab_size += strlen(&info->strtab[src->st_name]) + 1;
2206 2207 ndst++;
2207 while (!__test_and_set_bit(j, info->strmap)
2208 && info->strtab[j])
2209 ++j;
2210 ++ndst;
2211 } 2208 }
2212 2209
2213 /* Append room for core symbols at end of core part. */ 2210 /* Append room for core symbols at end of core part. */
2214 info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); 2211 info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
2215 mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym); 2212 info->stroffs = mod->core_size = info->symoffs + ndst * sizeof(Elf_Sym);
2213 mod->core_size += strtab_size;
2216 2214
2217 /* Put string table section at end of init part of module. */ 2215 /* Put string table section at end of init part of module. */
2218 strsect->sh_flags |= SHF_ALLOC; 2216 strsect->sh_flags |= SHF_ALLOC;
2219 strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect, 2217 strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
2220 info->index.str) | INIT_OFFSET_MASK; 2218 info->index.str) | INIT_OFFSET_MASK;
2221 DEBUGP("\t%s\n", info->secstrings + strsect->sh_name); 2219 DEBUGP("\t%s\n", info->secstrings + strsect->sh_name);
2222
2223 /* Append room for core symbols' strings at end of core part. */
2224 info->stroffs = mod->core_size;
2225
2226 /* First strtab byte (and first symtab entry) are zeroes. */
2227 __set_bit(0, info->strmap);
2228 mod->core_size += bitmap_weight(info->strmap, strsect->sh_size);
2229} 2220}
2230 2221
2231static void add_kallsyms(struct module *mod, const struct load_info *info) 2222static void add_kallsyms(struct module *mod, const struct load_info *info)
@@ -2246,22 +2237,19 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
2246 mod->symtab[i].st_info = elf_type(&mod->symtab[i], info); 2237 mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
2247 2238
2248 mod->core_symtab = dst = mod->module_core + info->symoffs; 2239 mod->core_symtab = dst = mod->module_core + info->symoffs;
2240 mod->core_strtab = s = mod->module_core + info->stroffs;
2249 src = mod->symtab; 2241 src = mod->symtab;
2250 *dst = *src; 2242 *dst = *src;
2243 *s++ = 0;
2251 for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { 2244 for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
2252 if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) 2245 if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
2253 continue; 2246 continue;
2247
2254 dst[ndst] = *src; 2248 dst[ndst] = *src;
2255 dst[ndst].st_name = bitmap_weight(info->strmap, 2249 dst[ndst++].st_name = s - mod->core_strtab;
2256 dst[ndst].st_name); 2250 s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
2257 ++ndst;
2258 } 2251 }
2259 mod->core_num_syms = ndst; 2252 mod->core_num_syms = ndst;
2260
2261 mod->core_strtab = s = mod->module_core + info->stroffs;
2262 for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i)
2263 if (test_bit(i, info->strmap))
2264 *++s = mod->strtab[i];
2265} 2253}
2266#else 2254#else
2267static inline void layout_symtab(struct module *mod, struct load_info *info) 2255static inline void layout_symtab(struct module *mod, struct load_info *info)
@@ -2751,27 +2739,18 @@ static struct module *layout_and_allocate(struct load_info *info)
2751 this is done generically; there doesn't appear to be any 2739 this is done generically; there doesn't appear to be any
2752 special cases for the architectures. */ 2740 special cases for the architectures. */
2753 layout_sections(mod, info); 2741 layout_sections(mod, info);
2754
2755 info->strmap = kzalloc(BITS_TO_LONGS(info->sechdrs[info->index.str].sh_size)
2756 * sizeof(long), GFP_KERNEL);
2757 if (!info->strmap) {
2758 err = -ENOMEM;
2759 goto free_percpu;
2760 }
2761 layout_symtab(mod, info); 2742 layout_symtab(mod, info);
2762 2743
2763 /* Allocate and move to the final place */ 2744 /* Allocate and move to the final place */
2764 err = move_module(mod, info); 2745 err = move_module(mod, info);
2765 if (err) 2746 if (err)
2766 goto free_strmap; 2747 goto free_percpu;
2767 2748
2768 /* Module has been copied to its final place now: return it. */ 2749 /* Module has been copied to its final place now: return it. */
2769 mod = (void *)info->sechdrs[info->index.mod].sh_addr; 2750 mod = (void *)info->sechdrs[info->index.mod].sh_addr;
2770 kmemleak_load_module(mod, info); 2751 kmemleak_load_module(mod, info);
2771 return mod; 2752 return mod;
2772 2753
2773free_strmap:
2774 kfree(info->strmap);
2775free_percpu: 2754free_percpu:
2776 percpu_modfree(mod); 2755 percpu_modfree(mod);
2777out: 2756out:
@@ -2781,7 +2760,6 @@ out:
2781/* mod is no longer valid after this! */ 2760/* mod is no longer valid after this! */
2782static void module_deallocate(struct module *mod, struct load_info *info) 2761static void module_deallocate(struct module *mod, struct load_info *info)
2783{ 2762{
2784 kfree(info->strmap);
2785 percpu_modfree(mod); 2763 percpu_modfree(mod);
2786 module_free(mod, mod->module_init); 2764 module_free(mod, mod->module_init);
2787 module_free(mod, mod->module_core); 2765 module_free(mod, mod->module_core);
@@ -2911,8 +2889,7 @@ static struct module *load_module(void __user *umod,
2911 if (err < 0) 2889 if (err < 0)
2912 goto unlink; 2890 goto unlink;
2913 2891
2914 /* Get rid of temporary copy and strmap. */ 2892 /* Get rid of temporary copy. */
2915 kfree(info.strmap);
2916 free_copy(&info); 2893 free_copy(&info);
2917 2894
2918 /* Done! */ 2895 /* Done! */