mirror of
https://github.com/torvalds/linux.git
synced 2024-12-23 19:31:53 +00:00
x86/unwind/orc: Add 'signal' field to ORC metadata
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
This commit is contained in:
parent
a20717aca3
commit
ffb1b4a410
@ -57,12 +57,14 @@ struct orc_entry {
|
|||||||
unsigned sp_reg:4;
|
unsigned sp_reg:4;
|
||||||
unsigned bp_reg:4;
|
unsigned bp_reg:4;
|
||||||
unsigned type:2;
|
unsigned type:2;
|
||||||
|
unsigned signal:1;
|
||||||
unsigned end:1;
|
unsigned end:1;
|
||||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||||
unsigned bp_reg:4;
|
unsigned bp_reg:4;
|
||||||
unsigned sp_reg:4;
|
unsigned sp_reg:4;
|
||||||
unsigned unused:5;
|
unsigned unused:4;
|
||||||
unsigned end:1;
|
unsigned end:1;
|
||||||
|
unsigned signal:1;
|
||||||
unsigned type:2;
|
unsigned type:2;
|
||||||
#endif
|
#endif
|
||||||
} __packed;
|
} __packed;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
|
UNWIND_HINT type=UNWIND_HINT_TYPE_ENTRY end=1
|
||||||
.endm
|
.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 \base == %rsp
|
||||||
.if \indirect
|
.if \indirect
|
||||||
.set sp_reg, ORC_REG_SP_INDIRECT
|
.set sp_reg, ORC_REG_SP_INDIRECT
|
||||||
@ -45,11 +45,11 @@
|
|||||||
.set type, UNWIND_HINT_TYPE_REGS
|
.set type, UNWIND_HINT_TYPE_REGS
|
||||||
.endif
|
.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
|
.endm
|
||||||
|
|
||||||
.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
|
.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0 signal=1
|
||||||
UNWIND_HINT_REGS base=\base offset=\offset partial=1
|
UNWIND_HINT_REGS base=\base offset=\offset partial=1 signal=\signal
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro UNWIND_HINT_FUNC
|
.macro UNWIND_HINT_FUNC
|
||||||
@ -67,7 +67,7 @@
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#define UNWIND_HINT_FUNC \
|
#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__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
|
@ -484,6 +484,8 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->signal = orc->signal;
|
||||||
|
|
||||||
/* Find the previous frame's stack: */
|
/* Find the previous frame's stack: */
|
||||||
switch (orc->sp_reg) {
|
switch (orc->sp_reg) {
|
||||||
case ORC_REG_SP:
|
case ORC_REG_SP:
|
||||||
@ -563,7 +565,6 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||||||
state->sp = sp;
|
state->sp = sp;
|
||||||
state->regs = NULL;
|
state->regs = NULL;
|
||||||
state->prev_regs = NULL;
|
state->prev_regs = NULL;
|
||||||
state->signal = false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNWIND_HINT_TYPE_REGS:
|
case UNWIND_HINT_TYPE_REGS:
|
||||||
@ -587,7 +588,6 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||||||
state->regs = (struct pt_regs *)sp;
|
state->regs = (struct pt_regs *)sp;
|
||||||
state->prev_regs = NULL;
|
state->prev_regs = NULL;
|
||||||
state->full_regs = true;
|
state->full_regs = true;
|
||||||
state->signal = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNWIND_HINT_TYPE_REGS_PARTIAL:
|
case UNWIND_HINT_TYPE_REGS_PARTIAL:
|
||||||
@ -604,7 +604,6 @@ bool unwind_next_frame(struct unwind_state *state)
|
|||||||
state->prev_regs = state->regs;
|
state->prev_regs = state->regs;
|
||||||
state->regs = (void *)sp - IRET_FRAME_OFFSET;
|
state->regs = (void *)sp - IRET_FRAME_OFFSET;
|
||||||
state->full_regs = false;
|
state->full_regs = false;
|
||||||
state->signal = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -15,6 +15,7 @@ struct unwind_hint {
|
|||||||
s16 sp_offset;
|
s16 sp_offset;
|
||||||
u8 sp_reg;
|
u8 sp_reg;
|
||||||
u8 type;
|
u8 type;
|
||||||
|
u8 signal;
|
||||||
u8 end;
|
u8 end;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -49,7 +50,7 @@ struct unwind_hint {
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
|
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
|
||||||
"987: \n\t" \
|
"987: \n\t" \
|
||||||
".pushsection .discard.unwind_hints\n\t" \
|
".pushsection .discard.unwind_hints\n\t" \
|
||||||
/* struct unwind_hint */ \
|
/* struct unwind_hint */ \
|
||||||
@ -57,6 +58,7 @@ struct unwind_hint {
|
|||||||
".short " __stringify(sp_offset) "\n\t" \
|
".short " __stringify(sp_offset) "\n\t" \
|
||||||
".byte " __stringify(sp_reg) "\n\t" \
|
".byte " __stringify(sp_reg) "\n\t" \
|
||||||
".byte " __stringify(type) "\n\t" \
|
".byte " __stringify(type) "\n\t" \
|
||||||
|
".byte " __stringify(signal) "\n\t" \
|
||||||
".byte " __stringify(end) "\n\t" \
|
".byte " __stringify(end) "\n\t" \
|
||||||
".balign 4 \n\t" \
|
".balign 4 \n\t" \
|
||||||
".popsection\n\t"
|
".popsection\n\t"
|
||||||
@ -129,7 +131,7 @@ struct unwind_hint {
|
|||||||
* the debuginfo as necessary. It will also warn if it sees any
|
* the debuginfo as necessary. It will also warn if it sees any
|
||||||
* inconsistencies.
|
* 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_\@:
|
.Lunwind_hint_ip_\@:
|
||||||
.pushsection .discard.unwind_hints
|
.pushsection .discard.unwind_hints
|
||||||
/* struct unwind_hint */
|
/* struct unwind_hint */
|
||||||
@ -137,6 +139,7 @@ struct unwind_hint {
|
|||||||
.short \sp_offset
|
.short \sp_offset
|
||||||
.byte \sp_reg
|
.byte \sp_reg
|
||||||
.byte \type
|
.byte \type
|
||||||
|
.byte \signal
|
||||||
.byte \end
|
.byte \end
|
||||||
.balign 4
|
.balign 4
|
||||||
.popsection
|
.popsection
|
||||||
@ -174,7 +177,7 @@ struct unwind_hint {
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
|
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
|
||||||
"\n\t"
|
"\n\t"
|
||||||
#define STACK_FRAME_NON_STANDARD(func)
|
#define STACK_FRAME_NON_STANDARD(func)
|
||||||
#define STACK_FRAME_NON_STANDARD_FP(func)
|
#define STACK_FRAME_NON_STANDARD_FP(func)
|
||||||
@ -182,7 +185,7 @@ struct unwind_hint {
|
|||||||
#define ASM_REACHABLE
|
#define ASM_REACHABLE
|
||||||
#else
|
#else
|
||||||
#define ANNOTATE_INTRA_FUNCTION_CALL
|
#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
|
.endm
|
||||||
.macro STACK_FRAME_NON_STANDARD func:req
|
.macro STACK_FRAME_NON_STANDARD func:req
|
||||||
.endm
|
.endm
|
||||||
|
@ -57,12 +57,14 @@ struct orc_entry {
|
|||||||
unsigned sp_reg:4;
|
unsigned sp_reg:4;
|
||||||
unsigned bp_reg:4;
|
unsigned bp_reg:4;
|
||||||
unsigned type:2;
|
unsigned type:2;
|
||||||
|
unsigned signal:1;
|
||||||
unsigned end:1;
|
unsigned end:1;
|
||||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||||
unsigned bp_reg:4;
|
unsigned bp_reg:4;
|
||||||
unsigned sp_reg:4;
|
unsigned sp_reg:4;
|
||||||
unsigned unused:5;
|
unsigned unused:4;
|
||||||
unsigned end:1;
|
unsigned end:1;
|
||||||
|
unsigned signal:1;
|
||||||
unsigned type:2;
|
unsigned type:2;
|
||||||
#endif
|
#endif
|
||||||
} __packed;
|
} __packed;
|
||||||
|
@ -15,6 +15,7 @@ struct unwind_hint {
|
|||||||
s16 sp_offset;
|
s16 sp_offset;
|
||||||
u8 sp_reg;
|
u8 sp_reg;
|
||||||
u8 type;
|
u8 type;
|
||||||
|
u8 signal;
|
||||||
u8 end;
|
u8 end;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -49,7 +50,7 @@ struct unwind_hint {
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
|
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
|
||||||
"987: \n\t" \
|
"987: \n\t" \
|
||||||
".pushsection .discard.unwind_hints\n\t" \
|
".pushsection .discard.unwind_hints\n\t" \
|
||||||
/* struct unwind_hint */ \
|
/* struct unwind_hint */ \
|
||||||
@ -57,6 +58,7 @@ struct unwind_hint {
|
|||||||
".short " __stringify(sp_offset) "\n\t" \
|
".short " __stringify(sp_offset) "\n\t" \
|
||||||
".byte " __stringify(sp_reg) "\n\t" \
|
".byte " __stringify(sp_reg) "\n\t" \
|
||||||
".byte " __stringify(type) "\n\t" \
|
".byte " __stringify(type) "\n\t" \
|
||||||
|
".byte " __stringify(signal) "\n\t" \
|
||||||
".byte " __stringify(end) "\n\t" \
|
".byte " __stringify(end) "\n\t" \
|
||||||
".balign 4 \n\t" \
|
".balign 4 \n\t" \
|
||||||
".popsection\n\t"
|
".popsection\n\t"
|
||||||
@ -129,7 +131,7 @@ struct unwind_hint {
|
|||||||
* the debuginfo as necessary. It will also warn if it sees any
|
* the debuginfo as necessary. It will also warn if it sees any
|
||||||
* inconsistencies.
|
* 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_\@:
|
.Lunwind_hint_ip_\@:
|
||||||
.pushsection .discard.unwind_hints
|
.pushsection .discard.unwind_hints
|
||||||
/* struct unwind_hint */
|
/* struct unwind_hint */
|
||||||
@ -137,6 +139,7 @@ struct unwind_hint {
|
|||||||
.short \sp_offset
|
.short \sp_offset
|
||||||
.byte \sp_reg
|
.byte \sp_reg
|
||||||
.byte \type
|
.byte \type
|
||||||
|
.byte \signal
|
||||||
.byte \end
|
.byte \end
|
||||||
.balign 4
|
.balign 4
|
||||||
.popsection
|
.popsection
|
||||||
@ -174,7 +177,7 @@ struct unwind_hint {
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
|
#define UNWIND_HINT(sp_reg, sp_offset, type, signal, end) \
|
||||||
"\n\t"
|
"\n\t"
|
||||||
#define STACK_FRAME_NON_STANDARD(func)
|
#define STACK_FRAME_NON_STANDARD(func)
|
||||||
#define STACK_FRAME_NON_STANDARD_FP(func)
|
#define STACK_FRAME_NON_STANDARD_FP(func)
|
||||||
@ -182,7 +185,7 @@ struct unwind_hint {
|
|||||||
#define ASM_REACHABLE
|
#define ASM_REACHABLE
|
||||||
#else
|
#else
|
||||||
#define ANNOTATE_INTRA_FUNCTION_CALL
|
#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
|
.endm
|
||||||
.macro STACK_FRAME_NON_STANDARD func:req
|
.macro STACK_FRAME_NON_STANDARD func:req
|
||||||
.endm
|
.endm
|
||||||
|
@ -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));
|
print_reg(orc[i].bp_reg, bswap_if_needed(&dummy_elf, orc[i].bp_offset));
|
||||||
|
|
||||||
printf(" type:%s end:%d\n",
|
printf(" type:%s signal:%d end:%d\n",
|
||||||
orc_type_name(orc[i].type), orc[i].end);
|
orc_type_name(orc[i].type), orc[i].signal, orc[i].end);
|
||||||
}
|
}
|
||||||
|
|
||||||
elf_end(elf);
|
elf_end(elf);
|
||||||
|
Loading…
Reference in New Issue
Block a user