Commit 8faea26e authored by Josh Poimboeuf's avatar Josh Poimboeuf Committed by Borislav Petkov
Browse files

objtool: Re-add UNWIND_HINT_{SAVE_RESTORE}



Commit

  c536ed2f ("objtool: Remove SAVE/RESTORE hints")

removed the save/restore unwind hints because they were no longer
needed. Now they're going to be needed again so re-add them.

Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent acac5e98
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -8,11 +8,11 @@
#ifdef __ASSEMBLY__

.macro UNWIND_HINT_EMPTY
	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED type=UNWIND_HINT_TYPE_CALL end=1
	UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1
.endm

.macro UNWIND_HINT_ENTRY
	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED type=UNWIND_HINT_TYPE_ENTRY end=1
	UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
.endm

.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0
@@ -56,6 +56,14 @@
	UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=8 type=UNWIND_HINT_TYPE_FUNC
.endm

.macro UNWIND_HINT_SAVE
	UNWIND_HINT type=UNWIND_HINT_TYPE_SAVE
.endm

.macro UNWIND_HINT_RESTORE
	UNWIND_HINT type=UNWIND_HINT_TYPE_RESTORE
.endm

#else

#define UNWIND_HINT_FUNC \
+4 −2
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ struct unwind_hint {
#define UNWIND_HINT_TYPE_REGS_PARTIAL	2
#define UNWIND_HINT_TYPE_FUNC		3
#define UNWIND_HINT_TYPE_ENTRY		4
#define UNWIND_HINT_TYPE_SAVE		5
#define UNWIND_HINT_TYPE_RESTORE	6

#ifdef CONFIG_OBJTOOL

@@ -127,7 +129,7 @@ struct unwind_hint {
 * the debuginfo as necessary.  It will also warn if it sees any
 * inconsistencies.
 */
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.Lunwind_hint_ip_\@:
	.pushsection .discard.unwind_hints
		/* struct unwind_hint */
@@ -180,7 +182,7 @@ struct unwind_hint {
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
+4 −2
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ struct unwind_hint {
#define UNWIND_HINT_TYPE_REGS_PARTIAL	2
#define UNWIND_HINT_TYPE_FUNC		3
#define UNWIND_HINT_TYPE_ENTRY		4
#define UNWIND_HINT_TYPE_SAVE		5
#define UNWIND_HINT_TYPE_RESTORE	6

#ifdef CONFIG_OBJTOOL

@@ -127,7 +129,7 @@ struct unwind_hint {
 * the debuginfo as necessary.  It will also warn if it sees any
 * inconsistencies.
 */
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.Lunwind_hint_ip_\@:
	.pushsection .discard.unwind_hints
		/* struct unwind_hint */
@@ -180,7 +182,7 @@ struct unwind_hint {
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
+40 −0
Original line number Diff line number Diff line
@@ -2032,6 +2032,17 @@ static int read_unwind_hints(struct objtool_file *file)

		insn->hint = true;

		if (hint->type == UNWIND_HINT_TYPE_SAVE) {
			insn->hint = false;
			insn->save = true;
			continue;
		}

		if (hint->type == UNWIND_HINT_TYPE_RESTORE) {
			insn->restore = true;
			continue;
		}

		if (hint->type == UNWIND_HINT_TYPE_REGS_PARTIAL) {
			struct symbol *sym = find_symbol_by_offset(insn->sec, insn->offset);

@@ -3329,6 +3340,35 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
			state.instr += insn->instr;

		if (insn->hint) {
			if (insn->restore) {
				struct instruction *save_insn, *i;

				i = insn;
				save_insn = NULL;

				sym_for_each_insn_continue_reverse(file, func, i) {
					if (i->save) {
						save_insn = i;
						break;
					}
				}

				if (!save_insn) {
					WARN_FUNC("no corresponding CFI save for CFI restore",
						  sec, insn->offset);
					return 1;
				}

				if (!save_insn->visited) {
					WARN_FUNC("objtool isn't smart enough to handle this CFI save/restore combo",
						  sec, insn->offset);
					return 1;
				}

				insn->cfi = save_insn->cfi;
				nr_cfi_reused++;
			}

			state.cfi = *insn->cfi;
		} else {
			/* XXX track if we actually changed state.cfi */
+10 −9
Original line number Diff line number Diff line
@@ -46,18 +46,19 @@ struct instruction {
	enum insn_type type;
	unsigned long immediate;

	u8 dead_end	: 1,
	u16 dead_end		: 1,
	   ignore		: 1,
	   ignore_alts		: 1,
	   hint			: 1,
	   save			: 1,
	   restore		: 1,
	   retpoline_safe	: 1,
	   noendbr		: 1,
	   entry		: 1;
		/* 1 bit hole */
		/* 7 bit hole */

	s8 instr;
	u8 visited;
	/* u8 hole */

	struct alt_group *alt_group;
	struct symbol *call_dest;