History

objtool: Fix reloc hash collision in find_reloc_by_dest_range()

In find_reloc_by_dest_range(), hash collisions can cause a high-offset relocation to appear when probing a low-offset hash bucket. Only return early when the best match found so far genuinely belongs to the current bucket (its offset is within the bucket's stride range). Otherwise, continue scanning later buckets which may contain lower-offset matches. This ensures the first reloc in the range gets returned.

Josh Poimboeuf committed 6 months ago

Commit a375e321 parent 5f49ec81 file · +4 −3Browse files

Unified · Split

tools/objtool/elf.c+4−3
@@ -315,8 +315,9 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam · 314 unmodified lines
315315 return NULL;
316316 }
317317
318+/* If there are multiple matches, return the first one in the range */
318319 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
319− unsigned long offset, unsigned int len)
320+ unsigned long offset, unsigned int len)
320321 {
321322 struct reloc *reloc, *r = NULL;
322323 struct section *rsec;
@@ -338,11 +339,11 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se · 15 unmodified lines
338339 r = reloc;
339340 }
340341 }
341− if (r)
342+ if (r && (reloc_offset(r) & OFFSET_STRIDE_MASK) == o)
342343 return r;
343344 }
344345
345− return NULL;
346+ return r;
346347 }
347348
348349 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset)