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.
Unified · Split
| @@ -315,8 +315,9 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam · 314 unmodified lines | |||
| 315 | return NULL; | 315 | return NULL; |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | /* If there are multiple matches, return the first one in the range */ | ||
| 318 | struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, | 319 | 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) |
| 320 | { | 321 | { |
| 321 | struct reloc *reloc, *r = NULL; | 322 | struct reloc *reloc, *r = NULL; |
| 322 | struct section *rsec; | 323 | struct section *rsec; |
| @@ -338,11 +339,11 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se · 15 unmodified lines | |||
| 338 | r = reloc; | 339 | r = reloc; |
| 339 | } | 340 | } |
| 340 | } | 341 | } |
| 341 | if (r) | 342 | if (r && (reloc_offset(r) & OFFSET_STRIDE_MASK) == o) |
| 342 | return r; | 343 | return r; |
| 343 | } | 344 | } |
| 344 | 345 | ||
| 345 | return NULL; | 346 | return r; |
| 346 | } | 347 | } |
| 347 | 348 | ||
| 348 | struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) | 349 | struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) |