Commit cce622ab authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool fix from Ingo Molnar:
 "Fix a segfault that occurs when built with Clang"

* tag 'objtool-urgent-2020-12-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  objtool: Fix seg fault with Clang non-section symbols
parents 6be5f582 44f6a7c0
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -467,13 +467,20 @@ static int create_static_call_sections(struct objtool_file *file)

		/* populate reloc for 'addr' */
		reloc = malloc(sizeof(*reloc));

		if (!reloc) {
			perror("malloc");
			return -1;
		}
		memset(reloc, 0, sizeof(*reloc));
		reloc->sym = insn->sec->sym;
		reloc->addend = insn->offset;

		insn_to_reloc_sym_addend(insn->sec, insn->offset, reloc);
		if (!reloc->sym) {
			WARN_FUNC("static call tramp: missing containing symbol",
				  insn->sec, insn->offset);
			return -1;
		}

		reloc->type = R_X86_64_PC32;
		reloc->offset = idx * sizeof(struct static_call_site);
		reloc->sec = reloc_sec;
+26 −0
Original line number Diff line number Diff line
@@ -262,6 +262,32 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
	return find_reloc_by_dest_range(elf, sec, offset, 1);
}

void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
			      struct reloc *reloc)
{
	if (sec->sym) {
		reloc->sym = sec->sym;
		reloc->addend = offset;
		return;
	}

	/*
	 * The Clang assembler strips section symbols, so we have to reference
	 * the function symbol instead:
	 */
	reloc->sym = find_symbol_containing(sec, offset);
	if (!reloc->sym) {
		/*
		 * Hack alert.  This happens when we need to reference the NOP
		 * pad insn immediately after the function.
		 */
		reloc->sym = find_symbol_containing(sec, offset - 1);
	}

	if (reloc->sym)
		reloc->addend = offset - reloc->sym->offset;
}

static int read_sections(struct elf *elf)
{
	Elf_Scn *s = NULL;
+2 −0
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, uns
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
				     unsigned long offset, unsigned int len);
struct symbol *find_func_containing(struct section *sec, unsigned long offset);
void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset,
			      struct reloc *reloc);
int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);

#define for_each_sec(file, sec)						\
+5 −24
Original line number Diff line number Diff line
@@ -105,32 +105,13 @@ static int create_orc_entry(struct elf *elf, struct section *u_sec, struct secti
	}
	memset(reloc, 0, sizeof(*reloc));

	if (insn_sec->sym) {
		reloc->sym = insn_sec->sym;
		reloc->addend = insn_off;
	} else {
		/*
		 * The Clang assembler doesn't produce section symbols, so we
		 * have to reference the function symbol instead:
		 */
		reloc->sym = find_symbol_containing(insn_sec, insn_off);
		if (!reloc->sym) {
			/*
			 * Hack alert.  This happens when we need to reference
			 * the NOP pad insn immediately after the function.
			 */
			reloc->sym = find_symbol_containing(insn_sec,
							   insn_off - 1);
		}
	insn_to_reloc_sym_addend(insn_sec, insn_off, reloc);
	if (!reloc->sym) {
			WARN("missing symbol for insn at offset 0x%lx\n",
		WARN("missing symbol for insn at offset 0x%lx",
		     insn_off);
		return -1;
	}

		reloc->addend = insn_off - reloc->sym->offset;
	}

	reloc->type = R_X86_64_PC32;
	reloc->offset = idx * sizeof(int);
	reloc->sec = ip_relocsec;