Skip to content

Commit b1a9651

Browse files
committed
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: Masahiro Yamada <masahiroy@kernel.org> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
1 parent 12ca2c6 commit b1a9651

File tree

1 file changed

+33
-56
lines changed

1 file changed

+33
-56
lines changed

scripts/mod/modpost.c

Lines changed: 33 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,79 +1075,56 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)
10751075
return !is_mapping_symbol(name);
10761076
}
10771077

1078-
/**
1079-
* Find symbol based on relocation record info.
1080-
* In some cases the symbol supplied is a valid symbol so
1081-
* return refsym. If is_valid_name() == true, we assume this is a valid symbol.
1082-
* In other cases the symbol needs to be looked up in the symbol table
1083-
* based on section and address.
1084-
* **/
1085-
static Elf_Sym *find_tosym(struct elf_info *elf, Elf64_Sword addr,
1086-
Elf_Sym *relsym)
1078+
/* Look up the nearest symbol based on the section and the address */
1079+
static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr,
1080+
unsigned int secndx, bool allow_negative,
1081+
Elf_Addr min_distance)
10871082
{
10881083
Elf_Sym *sym;
10891084
Elf_Sym *near = NULL;
1090-
Elf64_Sword distance = 20;
1091-
Elf64_Sword d;
1092-
unsigned int relsym_secindex;
1093-
1094-
if (is_valid_name(elf, relsym))
1095-
return relsym;
1085+
Elf_Addr distance;
10961086

1097-
/*
1098-
* Strive to find a better symbol name, but the resulting name may not
1099-
* match the symbol referenced in the original code.
1100-
*/
1101-
relsym_secindex = get_secindex(elf, relsym);
11021087
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1103-
if (get_secindex(elf, sym) != relsym_secindex)
1104-
continue;
1105-
if (ELF_ST_TYPE(sym->st_info) == STT_SECTION)
1088+
if (get_secindex(elf, sym) != secndx)
11061089
continue;
11071090
if (!is_valid_name(elf, sym))
11081091
continue;
1109-
if (sym->st_value == addr)
1110-
return sym;
1111-
/* Find a symbol nearby - addr are maybe negative */
1112-
d = sym->st_value - addr;
1113-
if (d < 0)
1114-
d = addr - sym->st_value;
1115-
if (d < distance) {
1116-
distance = d;
1092+
1093+
if (addr >= sym->st_value)
1094+
distance = addr - sym->st_value;
1095+
else if (allow_negative)
1096+
distance = sym->st_value - addr;
1097+
else
1098+
continue;
1099+
1100+
if (distance <= min_distance) {
1101+
min_distance = distance;
11171102
near = sym;
11181103
}
1104+
1105+
if (min_distance == 0)
1106+
break;
11191107
}
1120-
/* We need a close match */
1121-
if (distance < 20)
1122-
return near;
1123-
else
1124-
return NULL;
1108+
return near;
11251109
}
11261110

1127-
/*
1128-
* Find symbols before or equal addr and after addr - in the section sec.
1129-
* If we find two symbols with equal offset prefer one with a valid name.
1130-
* The ELF format may have a better way to detect what type of symbol
1131-
* it is, but this works for now.
1132-
**/
11331111
static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
11341112
unsigned int secndx)
11351113
{
1136-
Elf_Sym *sym;
1137-
Elf_Sym *near = NULL;
1138-
Elf_Addr distance = ~0;
1114+
return find_nearest_sym(elf, addr, secndx, false, ~0);
1115+
}
11391116

1140-
for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) {
1141-
if (get_secindex(elf, sym) != secndx)
1142-
continue;
1143-
if (!is_valid_name(elf, sym))
1144-
continue;
1145-
if (sym->st_value <= addr && addr - sym->st_value <= distance) {
1146-
distance = addr - sym->st_value;
1147-
near = sym;
1148-
}
1149-
}
1150-
return near;
1117+
static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
1118+
{
1119+
/* If the supplied symbol has a valid name, return it */
1120+
if (is_valid_name(elf, sym))
1121+
return sym;
1122+
1123+
/*
1124+
* Strive to find a better symbol name, but the resulting name may not
1125+
* match the symbol referenced in the original code.
1126+
*/
1127+
return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);
11511128
}
11521129

11531130
static bool is_executable_section(struct elf_info *elf, unsigned int secndx)

0 commit comments

Comments
 (0)