Skip to content

Commit

Permalink
x86/unwind/orc: Add 'signal' field to ORC metadata
Browse files Browse the repository at this point in the history
Add a 'signal' field which allows unwind hints to specify whether the
instruction pointer should be taken literally (like for most interrupts
and exceptions) rather than decremented (like for call stack return
addresses) when used to find the next ORC entry.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/d2c5ec4d83a45b513d8fd72fab59f1a8cfa46871.1676068346.git.jpoimboe@kernel.org
  • Loading branch information
jpoimboe authored and Ingo Molnar committed Feb 11, 2023
1 parent a20717a commit ffb1b4a
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 20 deletions.
4 changes: 3 additions & 1 deletion arch/x86/include/asm/orc_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ struct orc_entry {
unsigned sp_reg:4;
unsigned bp_reg:4;
unsigned type:2;
unsigned signal:1;
unsigned end:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
unsigned bp_reg:4;
unsigned sp_reg:4;
unsigned unused:5;
unsigned unused:4;
unsigned end:1;
unsigned signal:1;
unsigned type:2;
#endif
} __packed;
Expand Down
10 changes: 5 additions & 5 deletions arch/x86/include/asm/unwind_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
.endm

.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0
.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0 signal=1
.if \base == %rsp
.if \indirect
.set sp_reg, ORC_REG_SP_INDIRECT
Expand Down Expand Up @@ -45,11 +45,11 @@
.set type, UNWIND_HINT_TYPE_REGS
.endif

UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type signal=\signal
.endm

.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
UNWIND_HINT_REGS base=\base offset=\offset partial=1
.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0 signal=1
UNWIND_HINT_REGS base=\base offset=\offset partial=1 signal=\signal
.endm

.macro UNWIND_HINT_FUNC
Expand All @@ -67,7 +67,7 @@
#else

#define UNWIND_HINT_FUNC \
UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0)
UNWIND_HINT(ORC_REG_SP, 8, UNWIND_HINT_TYPE_FUNC, 0, 0)

#endif /* __ASSEMBLY__ */

Expand Down
5 changes: 2 additions & 3 deletions arch/x86/kernel/unwind_orc.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ bool unwind_next_frame(struct unwind_state *state)
goto the_end;
}

state->signal = orc->signal;

/* Find the previous frame's stack: */
switch (orc->sp_reg) {
case ORC_REG_SP:
Expand Down Expand Up @@ -563,7 +565,6 @@ bool unwind_next_frame(struct unwind_state *state)
state->sp = sp;
state->regs = NULL;
state->prev_regs = NULL;
state->signal = false;
break;

case UNWIND_HINT_TYPE_REGS:
Expand All @@ -587,7 +588,6 @@ bool unwind_next_frame(struct unwind_state *state)
state->regs = (struct pt_regs *)sp;
state->prev_regs = NULL;
state->full_regs = true;
state->signal = true;
break;

case UNWIND_HINT_TYPE_REGS_PARTIAL:
Expand All @@ -604,7 +604,6 @@ bool unwind_next_frame(struct unwind_state *state)
state->prev_regs = state->regs;
state->regs = (void *)sp - IRET_FRAME_OFFSET;
state->full_regs = false;
state->signal = true;
break;

default:
Expand Down
11 changes: 7 additions & 4 deletions include/linux/objtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct unwind_hint {
s16 sp_offset;
u8 sp_reg;
u8 type;
u8 signal;
u8 end;
};
#endif
Expand Down Expand Up @@ -49,14 +50,15 @@ struct unwind_hint {

#ifndef __ASSEMBLY__

#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
"987: \n\t" \
".pushsection .discard.unwind_hints\n\t" \
/* struct unwind_hint */ \
".long 987b - .\n\t" \
".short " __stringify(sp_offset) "\n\t" \
".byte " __stringify(sp_reg) "\n\t" \
".byte " __stringify(type) "\n\t" \
".byte " __stringify(signal) "\n\t" \
".byte " __stringify(end) "\n\t" \
".balign 4 \n\t" \
".popsection\n\t"
Expand Down Expand Up @@ -129,14 +131,15 @@ struct unwind_hint {
* the debuginfo as necessary. It will also warn if it sees any
* inconsistencies.
*/
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
.Lunwind_hint_ip_\@:
.pushsection .discard.unwind_hints
/* struct unwind_hint */
.long .Lunwind_hint_ip_\@ - .
.short \sp_offset
.byte \sp_reg
.byte \type
.byte \signal
.byte \end
.balign 4
.popsection
Expand Down Expand Up @@ -174,15 +177,15 @@ struct unwind_hint {

#ifndef __ASSEMBLY__

#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
"\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
Expand Down
4 changes: 3 additions & 1 deletion tools/arch/x86/include/asm/orc_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ struct orc_entry {
unsigned sp_reg:4;
unsigned bp_reg:4;
unsigned type:2;
unsigned signal:1;
unsigned end:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
unsigned bp_reg:4;
unsigned sp_reg:4;
unsigned unused:5;
unsigned unused:4;
unsigned end:1;
unsigned signal:1;
unsigned type:2;
#endif
} __packed;
Expand Down
11 changes: 7 additions & 4 deletions tools/include/linux/objtool.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct unwind_hint {
s16 sp_offset;
u8 sp_reg;
u8 type;
u8 signal;
u8 end;
};
#endif
Expand Down Expand Up @@ -49,14 +50,15 @@ struct unwind_hint {

#ifndef __ASSEMBLY__

#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
"987: \n\t" \
".pushsection .discard.unwind_hints\n\t" \
/* struct unwind_hint */ \
".long 987b - .\n\t" \
".short " __stringify(sp_offset) "\n\t" \
".byte " __stringify(sp_reg) "\n\t" \
".byte " __stringify(type) "\n\t" \
".byte " __stringify(signal) "\n\t" \
".byte " __stringify(end) "\n\t" \
".balign 4 \n\t" \
".popsection\n\t"
Expand Down Expand Up @@ -129,14 +131,15 @@ struct unwind_hint {
* the debuginfo as necessary. It will also warn if it sees any
* inconsistencies.
*/
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
.Lunwind_hint_ip_\@:
.pushsection .discard.unwind_hints
/* struct unwind_hint */
.long .Lunwind_hint_ip_\@ - .
.short \sp_offset
.byte \sp_reg
.byte \type
.byte \signal
.byte \end
.balign 4
.popsection
Expand Down Expand Up @@ -174,15 +177,15 @@ struct unwind_hint {

#ifndef __ASSEMBLY__

#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
"\n\t"
#define STACK_FRAME_NON_STANDARD(func)
#define STACK_FRAME_NON_STANDARD_FP(func)
#define ANNOTATE_NOENDBR
#define ASM_REACHABLE
#else
#define ANNOTATE_INTRA_FUNCTION_CALL
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 end=0
.macro UNWIND_HINT type:req sp_reg=0 sp_offset=0 signal=0 end=0
.endm
.macro STACK_FRAME_NON_STANDARD func:req
.endm
Expand Down
4 changes: 2 additions & 2 deletions tools/objtool/orc_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ int orc_dump(const char *_objname)

print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset));

printf(" type:%s end:%d\n",
orc_type_name(orc[i].type), orc[i].end);
printf(" type:%s signal:%d end:%d\n",
orc_type_name(orc[i].type), orc[i].signal, orc[i].end);
}

elf_end(elf);
Expand Down

0 comments on commit ffb1b4a

Please sign in to comment.