]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
objtool: Fix reloc hash collision in find_reloc_by_dest_range()
authorJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 21 Apr 2026 14:21:19 +0000 (07:21 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 5 May 2026 04:16:02 +0000 (21:16 -0700)
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.

Fixes: 74b873e49d92 ("objtool: Optimize find_rela_by_dest_range()")
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Song Liu <song@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
tools/objtool/elf.c

index 5a20dab683dd2a162b4387cb4264b476d377d13c..f41280e454ca46dc1a8f7ff0c40ee226a2e11d91 100644 (file)
@@ -315,8 +315,9 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
        return NULL;
 }
 
+/* If there are multiple matches, return the first one in the range */
 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
-                                    unsigned long offset, unsigned int len)
+                                      unsigned long offset, unsigned int len)
 {
        struct reloc *reloc, *r = NULL;
        struct section *rsec;
@@ -338,11 +339,11 @@ struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *se
                                        r = reloc;
                        }
                }
-               if (r)
+               if (r && (reloc_offset(r) & OFFSET_STRIDE_MASK) == o)
                        return r;
        }
 
-       return NULL;
+       return r;
 }
 
 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset)