Commit 14bda4e5 authored by Peter Zijlstra's avatar Peter Zijlstra
Browse files

Merge branch 'objtool/core' of...

Merge branch 'objtool/core' of git://git.kernel.org/pub/scm/linux/kernel/git/jpoimboe/linux into objtool/core
parents b3a9e3b9 fb414783
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -82,6 +82,6 @@ bool arch_callee_saved_reg(unsigned char reg);

unsigned long arch_jump_destination(struct instruction *insn);

unsigned long arch_dest_rela_offset(int addend);
unsigned long arch_dest_reloc_offset(int addend);

#endif /* _ARCH_H */
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ bool arch_callee_saved_reg(unsigned char reg)
	}
}

unsigned long arch_dest_rela_offset(int addend)
unsigned long arch_dest_reloc_offset(int addend)
{
	return addend + 4;
}
+98 −98
Original line number Diff line number Diff line
@@ -352,7 +352,7 @@ static struct instruction *find_last_insn(struct objtool_file *file,
static int add_dead_ends(struct objtool_file *file)
{
	struct section *sec;
	struct rela *rela;
	struct reloc *reloc;
	struct instruction *insn;

	/*
@@ -370,24 +370,24 @@ static int add_dead_ends(struct objtool_file *file)
	if (!sec)
		goto reachable;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}
		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (insn)
			insn = list_prev_entry(insn, list);
		else if (rela->addend == rela->sym->sec->len) {
			insn = find_last_insn(file, rela->sym->sec);
		else if (reloc->addend == reloc->sym->sec->len) {
			insn = find_last_insn(file, reloc->sym->sec);
			if (!insn) {
				WARN("can't find unreachable insn at %s+0x%x",
				     rela->sym->sec->name, rela->addend);
				     reloc->sym->sec->name, reloc->addend);
				return -1;
			}
		} else {
			WARN("can't find unreachable insn at %s+0x%x",
			     rela->sym->sec->name, rela->addend);
			     reloc->sym->sec->name, reloc->addend);
			return -1;
		}

@@ -405,24 +405,24 @@ reachable:
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}
		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (insn)
			insn = list_prev_entry(insn, list);
		else if (rela->addend == rela->sym->sec->len) {
			insn = find_last_insn(file, rela->sym->sec);
		else if (reloc->addend == reloc->sym->sec->len) {
			insn = find_last_insn(file, reloc->sym->sec);
			if (!insn) {
				WARN("can't find reachable insn at %s+0x%x",
				     rela->sym->sec->name, rela->addend);
				     reloc->sym->sec->name, reloc->addend);
				return -1;
			}
		} else {
			WARN("can't find reachable insn at %s+0x%x",
			     rela->sym->sec->name, rela->addend);
			     reloc->sym->sec->name, reloc->addend);
			return -1;
		}

@@ -440,26 +440,26 @@ static void add_ignores(struct objtool_file *file)
	struct instruction *insn;
	struct section *sec;
	struct symbol *func;
	struct rela *rela;
	struct reloc *reloc;

	sec = find_section_by_name(file->elf, ".rela.discard.func_stack_frame_non_standard");
	if (!sec)
		return;

	list_for_each_entry(rela, &sec->rela_list, list) {
		switch (rela->sym->type) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		switch (reloc->sym->type) {
		case STT_FUNC:
			func = rela->sym;
			func = reloc->sym;
			break;

		case STT_SECTION:
			func = find_func_by_offset(rela->sym->sec, rela->addend);
			func = find_func_by_offset(reloc->sym->sec, reloc->addend);
			if (!func)
				continue;
			break;

		default:
			WARN("unexpected relocation symbol type in %s: %d", sec->name, rela->sym->type);
			WARN("unexpected relocation symbol type in %s: %d", sec->name, reloc->sym->type);
			continue;
		}

@@ -579,20 +579,20 @@ static void add_uaccess_safe(struct objtool_file *file)
static int add_ignore_alternatives(struct objtool_file *file)
{
	struct section *sec;
	struct rela *rela;
	struct reloc *reloc;
	struct instruction *insn;

	sec = find_section_by_name(file->elf, ".rela.discard.ignore_alts");
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("bad .discard.ignore_alts entry");
			return -1;
@@ -610,7 +610,7 @@ static int add_ignore_alternatives(struct objtool_file *file)
static int add_jump_destinations(struct objtool_file *file)
{
	struct instruction *insn;
	struct rela *rela;
	struct reloc *reloc;
	struct section *dest_sec;
	unsigned long dest_off;

@@ -621,19 +621,19 @@ static int add_jump_destinations(struct objtool_file *file)
		if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET)
			continue;

		rela = find_rela_by_dest_range(file->elf, insn->sec,
		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
					       insn->offset, insn->len);
		if (!rela) {
		if (!reloc) {
			dest_sec = insn->sec;
			dest_off = arch_jump_destination(insn);
		} else if (rela->sym->type == STT_SECTION) {
			dest_sec = rela->sym->sec;
			dest_off = arch_dest_rela_offset(rela->addend);
		} else if (rela->sym->sec->idx) {
			dest_sec = rela->sym->sec;
			dest_off = rela->sym->sym.st_value +
				   arch_dest_rela_offset(rela->addend);
		} else if (strstr(rela->sym->name, "_indirect_thunk_")) {
		} else if (reloc->sym->type == STT_SECTION) {
			dest_sec = reloc->sym->sec;
			dest_off = arch_dest_reloc_offset(reloc->addend);
		} else if (reloc->sym->sec->idx) {
			dest_sec = reloc->sym->sec;
			dest_off = reloc->sym->sym.st_value +
				   arch_dest_reloc_offset(reloc->addend);
		} else if (strstr(reloc->sym->name, "_indirect_thunk_")) {
			/*
			 * Retpoline jumps are really dynamic jumps in
			 * disguise, so convert them accordingly.
@@ -647,7 +647,7 @@ static int add_jump_destinations(struct objtool_file *file)
			continue;
		} else {
			/* external sibling call */
			insn->call_dest = rela->sym;
			insn->call_dest = reloc->sym;
			continue;
		}

@@ -723,15 +723,15 @@ static int add_call_destinations(struct objtool_file *file)
{
	struct instruction *insn;
	unsigned long dest_off;
	struct rela *rela;
	struct reloc *reloc;

	for_each_insn(file, insn) {
		if (insn->type != INSN_CALL)
			continue;

		rela = find_rela_by_dest_range(file->elf, insn->sec,
		reloc = find_reloc_by_dest_range(file->elf, insn->sec,
					       insn->offset, insn->len);
		if (!rela) {
		if (!reloc) {
			dest_off = arch_jump_destination(insn);
			insn->call_dest = find_func_by_offset(insn->sec, dest_off);
			if (!insn->call_dest)
@@ -751,19 +751,19 @@ static int add_call_destinations(struct objtool_file *file)
				return -1;
			}

		} else if (rela->sym->type == STT_SECTION) {
			dest_off = arch_dest_rela_offset(rela->addend);
			insn->call_dest = find_func_by_offset(rela->sym->sec,
		} else if (reloc->sym->type == STT_SECTION) {
			dest_off = arch_dest_reloc_offset(reloc->addend);
			insn->call_dest = find_func_by_offset(reloc->sym->sec,
							      dest_off);
			if (!insn->call_dest) {
				WARN_FUNC("can't find call dest symbol at %s+0x%lx",
					  insn->sec, insn->offset,
					  rela->sym->sec->name,
					  reloc->sym->sec->name,
					  dest_off);
				return -1;
			}
		} else
			insn->call_dest = rela->sym;
			insn->call_dest = reloc->sym;

		/*
		 * Whatever stack impact regular CALLs have, should be undone
@@ -871,7 +871,7 @@ static int handle_group_alt(struct objtool_file *file,
		 */
		if ((insn->offset != special_alt->new_off ||
		    (insn->type != INSN_CALL && !is_static_jump(insn))) &&
		    find_rela_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) {
		    find_reloc_by_dest_range(file->elf, insn->sec, insn->offset, insn->len)) {

			WARN_FUNC("unsupported relocation in alternatives section",
				  insn->sec, insn->offset);
@@ -1017,34 +1017,34 @@ out:
}

static int add_jump_table(struct objtool_file *file, struct instruction *insn,
			    struct rela *table)
			    struct reloc *table)
{
	struct rela *rela = table;
	struct reloc *reloc = table;
	struct instruction *dest_insn;
	struct alternative *alt;
	struct symbol *pfunc = insn->func->pfunc;
	unsigned int prev_offset = 0;

	/*
	 * Each @rela is a switch table relocation which points to the target
	 * Each @reloc is a switch table relocation which points to the target
	 * instruction.
	 */
	list_for_each_entry_from(rela, &table->sec->rela_list, list) {
	list_for_each_entry_from(reloc, &table->sec->reloc_list, list) {

		/* Check for the end of the table: */
		if (rela != table && rela->jump_table_start)
		if (reloc != table && reloc->jump_table_start)
			break;

		/* Make sure the table entries are consecutive: */
		if (prev_offset && rela->offset != prev_offset + 8)
		if (prev_offset && reloc->offset != prev_offset + 8)
			break;

		/* Detect function pointers from contiguous objects: */
		if (rela->sym->sec == pfunc->sec &&
		    rela->addend == pfunc->offset)
		if (reloc->sym->sec == pfunc->sec &&
		    reloc->addend == pfunc->offset)
			break;

		dest_insn = find_insn(file, rela->sym->sec, rela->addend);
		dest_insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!dest_insn)
			break;

@@ -1060,7 +1060,7 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,

		alt->insn = dest_insn;
		list_add_tail(&alt->list, &insn->alts);
		prev_offset = rela->offset;
		prev_offset = reloc->offset;
	}

	if (!prev_offset) {
@@ -1115,11 +1115,11 @@ static int add_jump_table(struct objtool_file *file, struct instruction *insn,
 *
 *    NOTE: RETPOLINE made it harder still to decode dynamic jumps.
 */
static struct rela *find_jump_table(struct objtool_file *file,
static struct reloc *find_jump_table(struct objtool_file *file,
				      struct symbol *func,
				      struct instruction *insn)
{
	struct rela *text_rela, *table_rela;
	struct reloc *text_reloc, *table_reloc;
	struct instruction *dest_insn, *orig_insn = insn;
	struct section *table_sec;
	unsigned long table_offset;
@@ -1144,16 +1144,16 @@ static struct rela *find_jump_table(struct objtool_file *file,
		    break;

		/* look for a relocation which references .rodata */
		text_rela = find_rela_by_dest_range(file->elf, insn->sec,
		text_reloc = find_reloc_by_dest_range(file->elf, insn->sec,
						    insn->offset, insn->len);
		if (!text_rela || text_rela->sym->type != STT_SECTION ||
		    !text_rela->sym->sec->rodata)
		if (!text_reloc || text_reloc->sym->type != STT_SECTION ||
		    !text_reloc->sym->sec->rodata)
			continue;

		table_offset = text_rela->addend;
		table_sec = text_rela->sym->sec;
		table_offset = text_reloc->addend;
		table_sec = text_reloc->sym->sec;

		if (text_rela->type == R_X86_64_PC32)
		if (text_reloc->type == R_X86_64_PC32)
			table_offset += 4;

		/*
@@ -1170,14 +1170,14 @@ static struct rela *find_jump_table(struct objtool_file *file,
			continue;

		/*
		 * Each table entry has a rela associated with it.  The rela
		 * Each table entry has a reloc associated with it.  The reloc
		 * should reference text in the same function as the original
		 * instruction.
		 */
		table_rela = find_rela_by_dest(file->elf, table_sec, table_offset);
		if (!table_rela)
		table_reloc = find_reloc_by_dest(file->elf, table_sec, table_offset);
		if (!table_reloc)
			continue;
		dest_insn = find_insn(file, table_rela->sym->sec, table_rela->addend);
		dest_insn = find_insn(file, table_reloc->sym->sec, table_reloc->addend);
		if (!dest_insn || !dest_insn->func || dest_insn->func->pfunc != func)
			continue;

@@ -1186,10 +1186,10 @@ static struct rela *find_jump_table(struct objtool_file *file,
		 * indicates a rare GCC quirk/bug which can leave dead code
		 * behind.
		 */
		if (text_rela->type == R_X86_64_PC32)
		if (text_reloc->type == R_X86_64_PC32)
			file->ignore_unreachables = true;

		return table_rela;
		return table_reloc;
	}

	return NULL;
@@ -1203,7 +1203,7 @@ static void mark_func_jump_tables(struct objtool_file *file,
				    struct symbol *func)
{
	struct instruction *insn, *last = NULL;
	struct rela *rela;
	struct reloc *reloc;

	func_for_each_insn(file, func, insn) {
		if (!last)
@@ -1226,10 +1226,10 @@ static void mark_func_jump_tables(struct objtool_file *file,
		if (insn->type != INSN_JUMP_DYNAMIC)
			continue;

		rela = find_jump_table(file, func, insn);
		if (rela) {
			rela->jump_table_start = true;
			insn->jump_table = rela;
		reloc = find_jump_table(file, func, insn);
		if (reloc) {
			reloc->jump_table_start = true;
			insn->jump_table = reloc;
		}
	}
}
@@ -1283,8 +1283,8 @@ static int add_jump_table_alts(struct objtool_file *file)

static int read_unwind_hints(struct objtool_file *file)
{
	struct section *sec, *relasec;
	struct rela *rela;
	struct section *sec, *relocsec;
	struct reloc *reloc;
	struct unwind_hint *hint;
	struct instruction *insn;
	struct cfi_reg *cfa;
@@ -1294,8 +1294,8 @@ static int read_unwind_hints(struct objtool_file *file)
	if (!sec)
		return 0;

	relasec = sec->rela;
	if (!relasec) {
	relocsec = sec->reloc;
	if (!relocsec) {
		WARN("missing .rela.discard.unwind_hints section");
		return -1;
	}
@@ -1310,13 +1310,13 @@ static int read_unwind_hints(struct objtool_file *file)
	for (i = 0; i < sec->len / sizeof(struct unwind_hint); i++) {
		hint = (struct unwind_hint *)sec->data->d_buf + i;

		rela = find_rela_by_dest(file->elf, sec, i * sizeof(*hint));
		if (!rela) {
			WARN("can't find rela for unwind_hints[%d]", i);
		reloc = find_reloc_by_dest(file->elf, sec, i * sizeof(*hint));
		if (!reloc) {
			WARN("can't find reloc for unwind_hints[%d]", i);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("can't find insn for unwind_hints[%d]", i);
			return -1;
@@ -1374,19 +1374,19 @@ static int read_retpoline_hints(struct objtool_file *file)
{
	struct section *sec;
	struct instruction *insn;
	struct rela *rela;
	struct reloc *reloc;

	sec = find_section_by_name(file->elf, ".rela.discard.retpoline_safe");
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("bad .discard.retpoline_safe entry");
			return -1;
@@ -1409,19 +1409,19 @@ static int read_instr_hints(struct objtool_file *file)
{
	struct section *sec;
	struct instruction *insn;
	struct rela *rela;
	struct reloc *reloc;

	sec = find_section_by_name(file->elf, ".rela.discard.instr_end");
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("bad .discard.instr_end entry");
			return -1;
@@ -1434,13 +1434,13 @@ static int read_instr_hints(struct objtool_file *file)
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
		if (rela->sym->type != STT_SECTION) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s", sec->name);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("bad .discard.instr_begin entry");
			return -1;
@@ -1456,22 +1456,22 @@ static int read_intra_function_calls(struct objtool_file *file)
{
	struct instruction *insn;
	struct section *sec;
	struct rela *rela;
	struct reloc *reloc;

	sec = find_section_by_name(file->elf, ".rela.discard.intra_function_calls");
	if (!sec)
		return 0;

	list_for_each_entry(rela, &sec->rela_list, list) {
	list_for_each_entry(reloc, &sec->reloc_list, list) {
		unsigned long dest_off;

		if (rela->sym->type != STT_SECTION) {
		if (reloc->sym->type != STT_SECTION) {
			WARN("unexpected relocation symbol type in %s",
			     sec->name);
			return -1;
		}

		insn = find_insn(file, rela->sym->sec, rela->addend);
		insn = find_insn(file, reloc->sym->sec, reloc->addend);
		if (!insn) {
			WARN("bad .discard.intra_function_call entry");
			return -1;
+1 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ struct instruction {
	struct symbol *call_dest;
	struct instruction *jump_dest;
	struct instruction *first_jump_src;
	struct rela *jump_table;
	struct reloc *jump_table;
	struct list_head alts;
	struct symbol *func;
	struct list_head stack_ops;
+196 −79

File changed.

Preview size limit exceeded, changes collapsed.

Loading