mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
mod->core_symtab = dst = mod->module_core + info->symoffs;
+ mod->core_strtab = s = mod->module_core + info->stroffs;
src = mod->symtab;
*dst = *src;
+ *s++ = 0;
for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
+ const char *name;
if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
continue;
dst[ndst] = *src;
- dst[ndst].st_name = bitmap_weight(info->strmap,
- dst[ndst].st_name);
+
+ name = &mod->strtab[src->st_name];
+ if (unlikely(!test_bit(src->st_name, info->strmap))) {
+ /* Symbol name has already been copied; find it. */
+ char *dup;
+
+ for (dup = mod->core_strtab; strcmp(dup, name); dup++)
+ BUG_ON(dup > s);
+
+ dst[ndst].st_name = dup - mod->core_strtab;
+ } else {
+ /*
+ * Copy the symbol name to mod->core_strtab.
+ * "name" might point to the middle of a longer strtab
+ * entry, so backtrack to the first "required" byte
+ * of the string.
+ */
+ unsigned start = src->st_name, len = 0;
+
+ for (; test_bit(start - 1, info->strmap) &&
+ mod->strtab[start - 1]; start--)
+ len++;
+
+ dst[ndst].st_name = len + s - mod->core_strtab;
+ len += strlen(name) + 1;
+
+ memcpy(s, &mod->strtab[start], len);
+ s += len;
+ bitmap_clear(info->strmap, start, len);
+ }
++ndst;
}
mod->core_num_syms = ndst;
-
- mod->core_strtab = s = mod->module_core + info->stroffs;
- for (*s = 0, i = 1; i < info->sechdrs[info->index.str].sh_size; ++i)
- if (test_bit(i, info->strmap))
- *++s = mod->strtab[i];
}
#else
static inline void layout_symtab(struct module *mod, struct load_info *info)