]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
objtool: Get rid of reloc->addend
authorJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 30 May 2023 17:21:08 +0000 (10:21 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Wed, 7 Jun 2023 17:03:23 +0000 (10:03 -0700)
Get the addend from the embedded GElf_Rel[a] struct.

With allyesconfig + CONFIG_DEBUG_INFO:

- Before: peak heap memory consumption: 42.10G
- After:  peak heap memory consumption: 40.37G

Link: https://lore.kernel.org/r/ad2354f95d9ddd86094e3f7687acfa0750657784.1685464332.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
tools/objtool/arch/x86/decode.c
tools/objtool/arch/x86/special.c
tools/objtool/check.c
tools/objtool/elf.c
tools/objtool/include/objtool/elf.h
tools/objtool/special.c

index ffb12e83b2382e0ec97fb8a522dccac9fe5c8850..2e1caabecb1858679b2149d396bf7f078772c48e 100644 (file)
@@ -623,11 +623,11 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec
                        if (!immr || strcmp(immr->sym->name, "pv_ops"))
                                break;
 
-                       idx = (immr->addend + 8) / sizeof(void *);
+                       idx = (reloc_addend(immr) + 8) / sizeof(void *);
 
                        func = disp->sym;
                        if (disp->sym->type == STT_SECTION)
-                               func = find_symbol_by_offset(disp->sym->sec, disp->addend);
+                               func = find_symbol_by_offset(disp->sym->sec, reloc_addend(disp));
                        if (!func) {
                                WARN("no func for pv_ops[]");
                                return -1;
index 1a54a249cb504ef9c02de78c1325dd7b4d780706..65f48f35b97edee40d0b6d4620edcf55fbdd61bd 100644 (file)
@@ -105,7 +105,7 @@ struct reloc *arch_find_switch_table(struct objtool_file *file,
            !text_reloc->sym->sec->rodata)
                return NULL;
 
-       table_offset = text_reloc->addend;
+       table_offset = reloc_addend(text_reloc);
        table_sec = text_reloc->sym->sec;
 
        if (reloc_type(text_reloc) == R_X86_64_PC32)
index 04b4152be206dde92d97bb916f027fa4be1aa35e..745487dda43241cd15cb7351a99fb7e9173a9e1d 100644 (file)
@@ -509,7 +509,8 @@ static int add_pv_ops(struct objtool_file *file, const char *symname)
 
                func = reloc->sym;
                if (func->type == STT_SECTION)
-                       func = find_symbol_by_offset(reloc->sym->sec, reloc->addend);
+                       func = find_symbol_by_offset(reloc->sym->sec,
+                                                    reloc_addend(reloc));
 
                idx = (reloc_offset(reloc) - sym->offset) / sizeof(unsigned long);
 
@@ -583,6 +584,7 @@ static int add_dead_ends(struct objtool_file *file)
        struct section *rsec;
        struct reloc *reloc;
        struct instruction *insn;
+       s64 addend;
 
        /*
         * Check for manually annotated dead ends.
@@ -592,23 +594,27 @@ static int add_dead_ends(struct objtool_file *file)
                goto reachable;
 
        for_each_reloc(rsec, reloc) {
+
                if (reloc->sym->type != STT_SECTION) {
                        WARN("unexpected relocation symbol type in %s", rsec->name);
                        return -1;
                }
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+               addend = reloc_addend(reloc);
+
+               insn = find_insn(file, reloc->sym->sec, addend);
                if (insn)
                        insn = prev_insn_same_sec(file, insn);
-               else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+               else if (addend == reloc->sym->sec->sh.sh_size) {
                        insn = find_last_insn(file, reloc->sym->sec);
                        if (!insn) {
                                WARN("can't find unreachable insn at %s+0x%" PRIx64,
-                                    reloc->sym->sec->name, reloc->addend);
+                                    reloc->sym->sec->name, addend);
                                return -1;
                        }
                } else {
                        WARN("can't find unreachable insn at %s+0x%" PRIx64,
-                            reloc->sym->sec->name, reloc->addend);
+                            reloc->sym->sec->name, addend);
                        return -1;
                }
 
@@ -627,23 +633,27 @@ reachable:
                return 0;
 
        for_each_reloc(rsec, reloc) {
+
                if (reloc->sym->type != STT_SECTION) {
                        WARN("unexpected relocation symbol type in %s", rsec->name);
                        return -1;
                }
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+
+               addend = reloc_addend(reloc);
+
+               insn = find_insn(file, reloc->sym->sec, addend);
                if (insn)
                        insn = prev_insn_same_sec(file, insn);
-               else if (reloc->addend == reloc->sym->sec->sh.sh_size) {
+               else if (addend == reloc->sym->sec->sh.sh_size) {
                        insn = find_last_insn(file, reloc->sym->sec);
                        if (!insn) {
                                WARN("can't find reachable insn at %s+0x%" PRIx64,
-                                    reloc->sym->sec->name, reloc->addend);
+                                    reloc->sym->sec->name, addend);
                                return -1;
                        }
                } else {
                        WARN("can't find reachable insn at %s+0x%" PRIx64,
-                            reloc->sym->sec->name, reloc->addend);
+                            reloc->sym->sec->name, addend);
                        return -1;
                }
 
@@ -1026,7 +1036,7 @@ static void add_ignores(struct objtool_file *file)
                        break;
 
                case STT_SECTION:
-                       func = find_func_by_offset(reloc->sym->sec, reloc->addend);
+                       func = find_func_by_offset(reloc->sym->sec, reloc_addend(reloc));
                        if (!func)
                                continue;
                        break;
@@ -1266,7 +1276,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.ignore_alts entry");
                        return -1;
@@ -1542,7 +1552,7 @@ static int add_jump_destinations(struct objtool_file *file)
                        dest_off = arch_jump_destination(insn);
                } else if (reloc->sym->type == STT_SECTION) {
                        dest_sec = reloc->sym->sec;
-                       dest_off = arch_dest_reloc_offset(reloc->addend);
+                       dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
                } else if (reloc->sym->retpoline_thunk) {
                        add_retpoline_call(file, insn);
                        continue;
@@ -1559,7 +1569,7 @@ static int add_jump_destinations(struct objtool_file *file)
                } else if (reloc->sym->sec->idx) {
                        dest_sec = reloc->sym->sec;
                        dest_off = reloc->sym->sym.st_value +
-                                  arch_dest_reloc_offset(reloc->addend);
+                                  arch_dest_reloc_offset(reloc_addend(reloc));
                } else {
                        /* non-func asm code jumping to another file */
                        continue;
@@ -1676,7 +1686,7 @@ static int add_call_destinations(struct objtool_file *file)
                        }
 
                } else if (reloc->sym->type == STT_SECTION) {
-                       dest_off = arch_dest_reloc_offset(reloc->addend);
+                       dest_off = arch_dest_reloc_offset(reloc_addend(reloc));
                        dest = find_call_destination(reloc->sym->sec, dest_off);
                        if (!dest) {
                                WARN_INSN(insn, "can't find call dest symbol at %s+0x%lx",
@@ -2003,10 +2013,10 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 
                /* Detect function pointers from contiguous objects: */
                if (reloc->sym->sec == pfunc->sec &&
-                   reloc->addend == pfunc->offset)
+                   reloc_addend(reloc) == pfunc->offset)
                        break;
 
-               dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               dest_insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!dest_insn)
                        break;
 
@@ -2067,7 +2077,7 @@ static struct reloc *find_jump_table(struct objtool_file *file,
                table_reloc = arch_find_switch_table(file, insn);
                if (!table_reloc)
                        continue;
-               dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
+               dest_insn = find_insn(file, table_reloc->sym->sec, reloc_addend(table_reloc));
                if (!dest_insn || !insn_func(dest_insn) || insn_func(dest_insn)->pfunc != func)
                        continue;
 
@@ -2203,7 +2213,7 @@ static int read_unwind_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("can't find insn for unwind_hints[%d]", i);
                        return -1;
@@ -2271,7 +2281,8 @@ static int read_noendbr_hints(struct objtool_file *file)
                return 0;
 
        for_each_reloc(rsec, reloc) {
-               insn = find_insn(file, reloc->sym->sec, reloc->sym->offset + reloc->addend);
+               insn = find_insn(file, reloc->sym->sec,
+                                reloc->sym->offset + reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.noendbr entry");
                        return -1;
@@ -2299,7 +2310,7 @@ static int read_retpoline_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.retpoline_safe entry");
                        return -1;
@@ -2335,7 +2346,7 @@ static int read_instr_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.instr_end entry");
                        return -1;
@@ -2354,7 +2365,7 @@ static int read_instr_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.instr_begin entry");
                        return -1;
@@ -2382,7 +2393,7 @@ static int read_validate_unret_hints(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.instr_end entry");
                        return -1;
@@ -2413,7 +2424,7 @@ static int read_intra_function_calls(struct objtool_file *file)
                        return -1;
                }
 
-               insn = find_insn(file, reloc->sym->sec, reloc->addend);
+               insn = find_insn(file, reloc->sym->sec, reloc_addend(reloc));
                if (!insn) {
                        WARN("bad .discard.intra_function_call entry");
                        return -1;
@@ -3317,7 +3328,7 @@ static inline const char *call_dest_name(struct instruction *insn)
 
        reloc = insn_reloc(NULL, insn);
        if (reloc && !strcmp(reloc->sym->name, "pv_ops")) {
-               idx = (reloc->addend / sizeof(void *));
+               idx = (reloc_addend(reloc) / sizeof(void *));
                snprintf(pvname, sizeof(pvname), "pv_ops[%d]", idx);
                return pvname;
        }
@@ -3335,7 +3346,7 @@ static bool pv_call_dest(struct objtool_file *file, struct instruction *insn)
        if (!reloc || strcmp(reloc->sym->name, "pv_ops"))
                return false;
 
-       idx = (arch_dest_reloc_offset(reloc->addend) / sizeof(void *));
+       idx = (arch_dest_reloc_offset(reloc_addend(reloc)) / sizeof(void *));
 
        if (file->pv_ops[idx].clean)
                return true;
@@ -4279,9 +4290,9 @@ static int validate_ibt_insn(struct objtool_file *file, struct instruction *insn
                off = reloc->sym->offset;
                if (reloc_type(reloc) == R_X86_64_PC32 ||
                    reloc_type(reloc) == R_X86_64_PLT32)
-                       off += arch_dest_reloc_offset(reloc->addend);
+                       off += arch_dest_reloc_offset(reloc_addend(reloc));
                else
-                       off += reloc->addend;
+                       off += reloc_addend(reloc);
 
                dest = find_insn(file, reloc->sym->sec, off);
                if (!dest)
@@ -4338,7 +4349,7 @@ static int validate_ibt_data_reloc(struct objtool_file *file,
        struct instruction *dest;
 
        dest = find_insn(file, reloc->sym->sec,
-                        reloc->sym->offset + reloc->addend);
+                        reloc->sym->offset + reloc_addend(reloc));
        if (!dest)
                return 0;
 
index be9d24dcdf56b86026b8f7db7802cc192561a41a..16e019a1762c7568941680921d2aa23065d6bfc0 100644 (file)
@@ -833,10 +833,10 @@ static struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec,
 
        reloc->sec = rsec;
        reloc->sym = sym;
-       reloc->addend = addend;
 
        reloc->rel.r_offset = offset;
        reloc->rel.r_info = GELF_R_INFO(sym->idx, type);
+       reloc->rela.r_addend = addend;
 
        if (elf_write_reloc(elf, reloc))
                return NULL;
@@ -911,8 +911,6 @@ static int read_reloc(struct section *rsec, int i, struct reloc *reloc)
                return -1;
        }
 
-       reloc->addend = rela ? reloc->rela.r_addend : 0;
-
        return 0;
 }
 
@@ -1231,12 +1229,10 @@ int elf_write_reloc(struct elf *elf, struct reloc *reloc)
        struct section *rsec = reloc->sec;
        int ret;
 
-       if (rsec->sh.sh_type == SHT_RELA) {
-               reloc->rela.r_addend = reloc->addend;
+       if (rsec->sh.sh_type == SHT_RELA)
                ret = gelf_update_rela(rsec->data, reloc_idx(reloc), &reloc->rela);
-       } else {
+       else
                ret = gelf_update_rel(rsec->data, reloc_idx(reloc), &reloc->rel);
-       }
 
        if (!ret) {
                WARN_ELF("gelf_update_rela");
index 41d2149f8bb8a3b59c516f2beabdc34d794d9a69..be08b32a93ee1ace905dba8828e46b64cd410cf5 100644 (file)
@@ -75,7 +75,6 @@ struct reloc {
        struct section *sec;
        struct symbol *sym;
        struct list_head sym_reloc_entry;
-       s64 addend;
        bool jump_table_start;
 };
 
@@ -217,6 +216,11 @@ static inline void set_reloc_type(struct reloc *reloc, int type)
        reloc->rel.r_info = GELF_R_INFO(GELF_R_SYM(reloc->rel.r_info), type);
 }
 
+static inline s64 reloc_addend(struct reloc *reloc)
+{
+       return reloc->rela.r_addend;
+}
+
 #define for_each_sec(file, sec)                                                \
        list_for_each_entry(sec, &file->elf->sections, list)
 
index baa85c31526b389e49bb3f5da20947ca2af9f3cd..91b1950f5bd8a526dc21ae3f09eeae3356324a78 100644 (file)
@@ -62,7 +62,7 @@ static void reloc_to_sec_off(struct reloc *reloc, struct section **sec,
                             unsigned long *off)
 {
        *sec = reloc->sym->sec;
-       *off = reloc->sym->offset + reloc->addend;
+       *off = reloc->sym->offset + reloc_addend(reloc);
 }
 
 static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
@@ -126,7 +126,7 @@ static int get_alt_entry(struct elf *elf, const struct special_entry *entry,
                                  sec, offset + entry->key);
                        return -1;
                }
-               alt->key_addend = key_reloc->addend;
+               alt->key_addend = reloc_addend(key_reloc);
        }
 
        return 0;