objtool: Introduce CFI hash
commit 8b946cc38e063f0f7bb67789478c38f6d7d457c9 upstream. Andi reported that objtool on vmlinux.o consumes more memory than his system has, leading to horrific performance. This is in part because we keep a struct instruction for every instruction in the file in-memory. Shrink struct instruction by removing the CFI state (which includes full register state) from it and demand allocating it. Given most instructions don't actually change CFI state, there's lots of repetition there, so add a hash table to find previous CFI instances. Reduces memory consumption (and runtime) for processing an x86_64-allyesconfig: pre: 4:40.84 real, 143.99 user, 44.18 sys, 30624988 mem post: 2:14.61 real, 108.58 user, 25.04 sys, 16396184 mem Suggested-by: Andi Kleen <andi@firstfloor.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20210624095147.756759107@infradead.org Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> [bwh: Backported to 5.10: - Don't use bswap_if_needed() since we don't have any of the other fixes for mixed-endian cross-compilation - Since we don't have "objtool: Rewrite hashtable sizing", make cfi_hash_alloc() set the number of bits similarly to elf_hash_bits() - objtool doesn't have any mcount handling - Adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
e8b1128fb0
commit
9d7ec2418a
@@ -12,13 +12,19 @@
|
||||
#include "check.h"
|
||||
#include "warn.h"
|
||||
|
||||
static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi)
|
||||
static int init_orc_entry(struct orc_entry *orc, struct cfi_state *cfi,
|
||||
struct instruction *insn)
|
||||
{
|
||||
struct instruction *insn = container_of(cfi, struct instruction, cfi);
|
||||
struct cfi_reg *bp = &cfi->regs[CFI_BP];
|
||||
|
||||
memset(orc, 0, sizeof(*orc));
|
||||
|
||||
if (!cfi) {
|
||||
orc->end = 0;
|
||||
orc->sp_reg = ORC_REG_UNDEFINED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
orc->end = cfi->end;
|
||||
|
||||
if (cfi->cfa.base == CFI_UNDEFINED) {
|
||||
@@ -159,7 +165,7 @@ int orc_create(struct objtool_file *file)
|
||||
int i;
|
||||
|
||||
if (!alt_group) {
|
||||
if (init_orc_entry(&orc, &insn->cfi))
|
||||
if (init_orc_entry(&orc, insn->cfi, insn))
|
||||
return -1;
|
||||
if (!memcmp(&prev_orc, &orc, sizeof(orc)))
|
||||
continue;
|
||||
@@ -183,7 +189,8 @@ int orc_create(struct objtool_file *file)
|
||||
struct cfi_state *cfi = alt_group->cfi[i];
|
||||
if (!cfi)
|
||||
continue;
|
||||
if (init_orc_entry(&orc, cfi))
|
||||
/* errors are reported on the original insn */
|
||||
if (init_orc_entry(&orc, cfi, insn))
|
||||
return -1;
|
||||
if (!memcmp(&prev_orc, &orc, sizeof(orc)))
|
||||
continue;
|
||||
|
Reference in New Issue
Block a user