Skip to content

Commit 74b873e

Browse files
author
Peter Zijlstra
committed
objtool: Optimize find_rela_by_dest_range()
Perf shows there is significant time in find_rela_by_dest(); this is because we have to iterate the address space per byte, looking for relocation entries. Optimize this by reducing the address space granularity. This reduces objtool on vmlinux.o runtime from 4.8 to 4.4 seconds. Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Miroslav Benes <[email protected]> Acked-by: Josh Poimboeuf <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 8887a86 commit 74b873e

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

tools/objtool/elf.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,20 +215,27 @@ struct symbol *find_symbol_by_name(struct elf *elf, const char *name)
215215
struct rela *find_rela_by_dest_range(struct elf *elf, struct section *sec,
216216
unsigned long offset, unsigned int len)
217217
{
218-
struct rela *rela;
218+
struct rela *rela, *r = NULL;
219219
unsigned long o;
220220

221221
if (!sec->rela)
222222
return NULL;
223223

224224
sec = sec->rela;
225225

226-
for (o = offset; o < offset + len; o++) {
226+
for_offset_range(o, offset, offset + len) {
227227
hash_for_each_possible(elf->rela_hash, rela, hash,
228228
sec_offset_hash(sec, o)) {
229-
if (rela->sec == sec && rela->offset == o)
230-
return rela;
229+
if (rela->sec != sec)
230+
continue;
231+
232+
if (rela->offset >= offset && rela->offset < offset + len) {
233+
if (!r || rela->offset < r->offset)
234+
r = rela;
235+
}
231236
}
237+
if (r)
238+
return r;
232239
}
233240

234241
return NULL;

tools/objtool/elf.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,23 @@ struct elf {
8383
DECLARE_HASHTABLE(rela_hash, 20);
8484
};
8585

86+
#define OFFSET_STRIDE_BITS 4
87+
#define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS)
88+
#define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1))
89+
90+
#define for_offset_range(_offset, _start, _end) \
91+
for (_offset = ((_start) & OFFSET_STRIDE_MASK); \
92+
_offset <= ((_end) & OFFSET_STRIDE_MASK); \
93+
_offset += OFFSET_STRIDE)
94+
8695
static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
8796
{
88-
u32 ol = offset, oh = offset >> 32, idx = sec->idx;
97+
u32 ol, oh, idx = sec->idx;
98+
99+
offset &= OFFSET_STRIDE_MASK;
100+
101+
ol = offset;
102+
oh = offset >> 32;
89103

90104
__jhash_mix(ol, oh, idx);
91105

0 commit comments

Comments
 (0)