mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-07 10:29:52 +00:00
modpost: Optimize symbol search from linear to binary search
[ Upstream commit4074532758] Modify modpost to use binary search for converting addresses back into symbol references. Previously it used linear search. This change saves a few seconds of wall time for defconfig builds, but can save several minutes on allyesconfigs. Before: $ make LLVM=1 -j128 allyesconfig vmlinux -s KCFLAGS="-Wno-error" $ time scripts/mod/modpost -M -m -a -N -o vmlinux.symvers vmlinux.o 198.38user 1.27system 3:19.71elapsed After: $ make LLVM=1 -j128 allyesconfig vmlinux -s KCFLAGS="-Wno-error" $ time scripts/mod/modpost -M -m -a -N -o vmlinux.symvers vmlinux.o 11.91user 0.85system 0:12.78elapsed Signed-off-by: Jack Brennen <jbrennen@google.com> Tested-by: Nick Desaulniers <ndesaulniers@google.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> Stable-dep-of:1102f9f85b("modpost: do not make find_tosym() return NULL") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
55ed6c4778
commit
2bc92c61c5
@@ -22,7 +22,6 @@
|
||||
#include <errno.h>
|
||||
#include "modpost.h"
|
||||
#include "../../include/linux/license.h"
|
||||
#include "../../include/linux/module_symbol.h"
|
||||
|
||||
static bool module_enabled;
|
||||
/* Are we using CONFIG_MODVERSIONS? */
|
||||
@@ -577,11 +576,14 @@ static int parse_elf(struct elf_info *info, const char *filename)
|
||||
*p = TO_NATIVE(*p);
|
||||
}
|
||||
|
||||
symsearch_init(info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void parse_elf_finish(struct elf_info *info)
|
||||
{
|
||||
symsearch_finish(info);
|
||||
release_file(info->hdr, info->size);
|
||||
}
|
||||
|
||||
@@ -1042,71 +1044,10 @@ static int secref_whitelist(const char *fromsec, const char *fromsym,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no name there, ignore it; likewise, ignore it if it's
|
||||
* one of the magic symbols emitted used by current tools.
|
||||
*
|
||||
* Otherwise if find_symbols_between() returns those symbols, they'll
|
||||
* fail the whitelist tests and cause lots of false alarms ... fixable
|
||||
* only by merging __exit and __init sections into __text, bloating
|
||||
* the kernel (which is especially evil on embedded platforms).
|
||||
*/
|
||||
static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
|
||||
{
|
||||
const char *name = elf->strtab + sym->st_name;
|
||||
|
||||
if (!name || !strlen(name))
|
||||
return 0;
|
||||
return !is_mapping_symbol(name);
|
||||
}
|
||||
|
||||
/* Look up the nearest symbol based on the section and the address */
|
||||
static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr,
|
||||
unsigned int secndx, bool allow_negative,
|
||||
Elf_Addr min_distance)
|
||||
{
|
||||
Elf_Sym *sym;
|
||||
Elf_Sym *near = NULL;
|
||||
Elf_Addr sym_addr, distance;
|
||||
bool is_arm = (elf->hdr->e_machine == EM_ARM);
|
||||
|
||||
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
|
||||
if (get_secindex(elf, sym) != secndx)
|
||||
continue;
|
||||
if (!is_valid_name(elf, sym))
|
||||
continue;
|
||||
|
||||
sym_addr = sym->st_value;
|
||||
|
||||
/*
|
||||
* For ARM Thumb instruction, the bit 0 of st_value is set
|
||||
* if the symbol is STT_FUNC type. Mask it to get the address.
|
||||
*/
|
||||
if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC)
|
||||
sym_addr &= ~1;
|
||||
|
||||
if (addr >= sym_addr)
|
||||
distance = addr - sym_addr;
|
||||
else if (allow_negative)
|
||||
distance = sym_addr - addr;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (distance <= min_distance) {
|
||||
min_distance = distance;
|
||||
near = sym;
|
||||
}
|
||||
|
||||
if (min_distance == 0)
|
||||
break;
|
||||
}
|
||||
return near;
|
||||
}
|
||||
|
||||
static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
|
||||
unsigned int secndx)
|
||||
{
|
||||
return find_nearest_sym(elf, addr, secndx, false, ~0);
|
||||
return symsearch_find_nearest(elf, addr, secndx, false, ~0);
|
||||
}
|
||||
|
||||
static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
|
||||
@@ -1119,7 +1060,8 @@ static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
|
||||
* Strive to find a better symbol name, but the resulting name may not
|
||||
* match the symbol referenced in the original code.
|
||||
*/
|
||||
return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);
|
||||
return symsearch_find_nearest(elf, addr, get_secindex(elf, sym),
|
||||
true, 20);
|
||||
}
|
||||
|
||||
static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
|
||||
|
||||
Reference in New Issue
Block a user