Commit 0696b6e3 authored by Josh Poimboeuf's avatar Josh Poimboeuf
Browse files

objtool: Get rid of reloc->addend

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: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
parent fcee899d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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)
+40 −29
Original line number Diff line number Diff line
@@ -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 @@ static int add_dead_ends(struct objtool_file *file)
		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;

+3 −7
Original line number Diff line number Diff line
@@ -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");
+5 −1
Original line number Diff line number Diff line
@@ -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)

Loading