@@ -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- **/
11331111static 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
11531130static bool is_executable_section (struct elf_info * elf , unsigned int secndx )
0 commit comments