Commit b1a9651d authored by Masahiro Yamada's avatar Masahiro Yamada

modpost: refactor find_fromsym() and find_tosym()

find_fromsym() and find_tosym() are similar - both of them iterate
in the .symtab section and return the nearest symbol.

The difference between them is that find_tosym() allows a negative
distance, but the distance must be less than 20.

Factor out the common part into find_nearest_sym().
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
Reviewed-by: default avatarNick Desaulniers <ndesaulniers@google.com>
parent 12ca2c67
...@@ -1075,79 +1075,56 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) ...@@ -1075,79 +1075,56 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
return !is_mapping_symbol(name); return !is_mapping_symbol(name);
} }
/** /* Look up the nearest symbol based on the section and the address */
* Find symbol based on relocation record info. static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr,
* In some cases the symbol supplied is a valid symbol so unsigned int secndx, bool allow_negative,
* return refsym. If is_valid_name() == true, we assume this is a valid symbol. Elf_Addr min_distance)
* In other cases the symbol needs to be looked up in the symbol table
* based on section and address.
* **/
static Elf_Sym *find_tosym(struct elf_info *elf, Elf64_Sword addr,
Elf_Sym *relsym)
{ {
Elf_Sym *sym; Elf_Sym *sym;
Elf_Sym *near = NULL; Elf_Sym *near = NULL;
Elf64_Sword distance = 20; Elf_Addr distance;
Elf64_Sword d;
unsigned int relsym_secindex;
if (is_valid_name(elf, relsym))
return relsym;
/*
* Strive to find a better symbol name, but the resulting name may not
* match the symbol referenced in the original code.
*/
relsym_secindex = get_secindex(elf, relsym);
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
if (get_secindex(elf, sym) != relsym_secindex) if (get_secindex(elf, sym) != secndx)
continue;
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
continue; continue;
if (!is_valid_name(elf, sym)) if (!is_valid_name(elf, sym))
continue; continue;
if (sym->st_value == addr)
return sym; if (addr >= sym->st_value)
/* Find a symbol nearby - addr are maybe negative */ distance = addr - sym->st_value;
d = sym->st_value - addr; else if (allow_negative)
if (d < 0) distance = sym->st_value - addr;
d = addr - sym->st_value; else
if (d < distance) { continue;
distance = d;
if (distance <= min_distance) {
min_distance = distance;
near = sym; near = sym;
} }
if (min_distance == 0)
break;
} }
/* We need a close match */ return near;
if (distance < 20)
return near;
else
return NULL;
} }
/*
* Find symbols before or equal addr and after addr - in the section sec.
* If we find two symbols with equal offset prefer one with a valid name.
* The ELF format may have a better way to detect what type of symbol
* it is, but this works for now.
**/
static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr, static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
unsigned int secndx) unsigned int secndx)
{ {
Elf_Sym *sym; return find_nearest_sym(elf, addr, secndx, false, ~0);
Elf_Sym *near = NULL; }
Elf_Addr distance = ~0;
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
if (get_secindex(elf, sym) != secndx) {
continue; /* If the supplied symbol has a valid name, return it */
if (!is_valid_name(elf, sym)) if (is_valid_name(elf, sym))
continue; return sym;
if (sym->st_value <= addr && addr - sym->st_value <= distance) {
distance = addr - sym->st_value; /*
near = sym; * Strive to find a better symbol name, but the resulting name may not
} * match the symbol referenced in the original code.
} */
return near; return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);
} }
static bool is_executable_section(struct elf_info *elf, unsigned int secndx) static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment