Skip to content

Commit ee819ae

Browse files
Julien Thierryjpoimboe
authored andcommitted
objtool: Make unwind hint definitions available to other architectures
Unwind hints are useful to provide objtool with information about stack states in non-standard functions/code. While the type of information being provided might be very arch specific, the mechanism to provide the information can be useful for other architectures. Move the relevant unwint hint definitions for all architectures to see. [ jpoimboe: REGS_IRET -> REGS_PARTIAL ] Signed-off-by: Julien Thierry <jthierry@redhat.com> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
1 parent 5567c6c commit ee819ae

10 files changed

Lines changed: 249 additions & 125 deletions

File tree

arch/x86/include/asm/orc_types.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,6 @@
3939
#define ORC_REG_SP_INDIRECT 9
4040
#define ORC_REG_MAX 15
4141

42-
/*
43-
* ORC_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP (the
44-
* caller's SP right before it made the call). Used for all callable
45-
* functions, i.e. all C code and all callable asm functions.
46-
*
47-
* ORC_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset points
48-
* to a fully populated pt_regs from a syscall, interrupt, or exception.
49-
*
50-
* ORC_TYPE_REGS_IRET: Used in entry code to indicate that sp_reg+sp_offset
51-
* points to the iret return frame.
52-
*
53-
* The UNWIND_HINT macros are used only for the unwind_hint struct. They
54-
* aren't used in struct orc_entry due to size and complexity constraints.
55-
* Objtool converts them to real types when it converts the hints to orc
56-
* entries.
57-
*/
58-
#define ORC_TYPE_CALL 0
59-
#define ORC_TYPE_REGS 1
60-
#define ORC_TYPE_REGS_IRET 2
61-
#define UNWIND_HINT_TYPE_RET_OFFSET 3
62-
6342
#ifndef __ASSEMBLY__
6443
/*
6544
* This struct is more or less a vastly simplified version of the DWARF Call
@@ -78,19 +57,6 @@ struct orc_entry {
7857
unsigned end:1;
7958
} __packed;
8059

81-
/*
82-
* This struct is used by asm and inline asm code to manually annotate the
83-
* location of registers on the stack for the ORC unwinder.
84-
*
85-
* Type can be either ORC_TYPE_* or UNWIND_HINT_TYPE_*.
86-
*/
87-
struct unwind_hint {
88-
u32 ip;
89-
s16 sp_offset;
90-
u8 sp_reg;
91-
u8 type;
92-
u8 end;
93-
};
9460
#endif /* __ASSEMBLY__ */
9561

9662
#endif /* _ORC_TYPES_H */

arch/x86/include/asm/unwind_hints.h

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,17 @@
11
#ifndef _ASM_X86_UNWIND_HINTS_H
22
#define _ASM_X86_UNWIND_HINTS_H
33

4+
#include <linux/objtool.h>
5+
46
#include "orc_types.h"
57

68
#ifdef __ASSEMBLY__
79

8-
/*
9-
* In asm, there are two kinds of code: normal C-type callable functions and
10-
* the rest. The normal callable functions can be called by other code, and
11-
* don't do anything unusual with the stack. Such normal callable functions
12-
* are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
13-
* category. In this case, no special debugging annotations are needed because
14-
* objtool can automatically generate the ORC data for the ORC unwinder to read
15-
* at runtime.
16-
*
17-
* Anything which doesn't fall into the above category, such as syscall and
18-
* interrupt handlers, tends to not be called directly by other functions, and
19-
* often does unusual non-C-function-type things with the stack pointer. Such
20-
* code needs to be annotated such that objtool can understand it. The
21-
* following CFI hint macros are for this type of code.
22-
*
23-
* These macros provide hints to objtool about the state of the stack at each
24-
* instruction. Objtool starts from the hints and follows the code flow,
25-
* making automatic CFI adjustments when it sees pushes and pops, filling out
26-
* the debuginfo as necessary. It will also warn if it sees any
27-
* inconsistencies.
28-
*/
29-
.macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL end=0
30-
#ifdef CONFIG_STACK_VALIDATION
31-
.Lunwind_hint_ip_\@:
32-
.pushsection .discard.unwind_hints
33-
/* struct unwind_hint */
34-
.long .Lunwind_hint_ip_\@ - .
35-
.short \sp_offset
36-
.byte \sp_reg
37-
.byte \type
38-
.byte \end
39-
.balign 4
40-
.popsection
41-
#endif
42-
.endm
43-
4410
.macro UNWIND_HINT_EMPTY
45-
UNWIND_HINT sp_reg=ORC_REG_UNDEFINED end=1
11+
UNWIND_HINT sp_reg=ORC_REG_UNDEFINED type=UNWIND_HINT_TYPE_CALL end=1
4612
.endm
4713

48-
.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0
14+
.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0
4915
.if \base == %rsp
5016
.if \indirect
5117
.set sp_reg, ORC_REG_SP_INDIRECT
@@ -66,24 +32,24 @@
6632

6733
.set sp_offset, \offset
6834

69-
.if \iret
70-
.set type, ORC_TYPE_REGS_IRET
35+
.if \partial
36+
.set type, UNWIND_HINT_TYPE_REGS_PARTIAL
7137
.elseif \extra == 0
72-
.set type, ORC_TYPE_REGS_IRET
38+
.set type, UNWIND_HINT_TYPE_REGS_PARTIAL
7339
.set sp_offset, \offset + (16*8)
7440
.else
75-
.set type, ORC_TYPE_REGS
41+
.set type, UNWIND_HINT_TYPE_REGS
7642
.endif
7743

7844
UNWIND_HINT sp_reg=sp_reg sp_offset=sp_offset type=type
7945
.endm
8046

8147
.macro UNWIND_HINT_IRET_REGS base=%rsp offset=0
82-
UNWIND_HINT_REGS base=\base offset=\offset iret=1
48+
UNWIND_HINT_REGS base=\base offset=\offset partial=1
8349
.endm
8450

8551
.macro UNWIND_HINT_FUNC sp_offset=8
86-
UNWIND_HINT sp_offset=\sp_offset
52+
UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=\sp_offset type=UNWIND_HINT_TYPE_CALL
8753
.endm
8854

8955
/*
@@ -92,7 +58,7 @@
9258
* initial_func_cfi.
9359
*/
9460
.macro UNWIND_HINT_RET_OFFSET sp_offset=8
95-
UNWIND_HINT type=UNWIND_HINT_TYPE_RET_OFFSET sp_offset=\sp_offset
61+
UNWIND_HINT sp_reg=ORC_REG_SP type=UNWIND_HINT_TYPE_RET_OFFSET sp_offset=\sp_offset
9662
.endm
9763

9864
#endif /* __ASSEMBLY__ */

arch/x86/kernel/unwind_orc.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <linux/objtool.h>
23
#include <linux/module.h>
34
#include <linux/sort.h>
45
#include <asm/ptrace.h>
@@ -127,12 +128,12 @@ static struct orc_entry null_orc_entry = {
127128
.sp_offset = sizeof(long),
128129
.sp_reg = ORC_REG_SP,
129130
.bp_reg = ORC_REG_UNDEFINED,
130-
.type = ORC_TYPE_CALL
131+
.type = UNWIND_HINT_TYPE_CALL
131132
};
132133

133134
/* Fake frame pointer entry -- used as a fallback for generated code */
134135
static struct orc_entry orc_fp_entry = {
135-
.type = ORC_TYPE_CALL,
136+
.type = UNWIND_HINT_TYPE_CALL,
136137
.sp_reg = ORC_REG_BP,
137138
.sp_offset = 16,
138139
.bp_reg = ORC_REG_PREV_SP,
@@ -531,7 +532,7 @@ bool unwind_next_frame(struct unwind_state *state)
531532

532533
/* Find IP, SP and possibly regs: */
533534
switch (orc->type) {
534-
case ORC_TYPE_CALL:
535+
case UNWIND_HINT_TYPE_CALL:
535536
ip_p = sp - sizeof(long);
536537

537538
if (!deref_stack_reg(state, ip_p, &state->ip))
@@ -546,7 +547,7 @@ bool unwind_next_frame(struct unwind_state *state)
546547
state->signal = false;
547548
break;
548549

549-
case ORC_TYPE_REGS:
550+
case UNWIND_HINT_TYPE_REGS:
550551
if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
551552
orc_warn_current("can't access registers at %pB\n",
552553
(void *)orig_ip);
@@ -559,7 +560,7 @@ bool unwind_next_frame(struct unwind_state *state)
559560
state->signal = true;
560561
break;
561562

562-
case ORC_TYPE_REGS_IRET:
563+
case UNWIND_HINT_TYPE_REGS_PARTIAL:
563564
if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
564565
orc_warn_current("can't access iret registers at %pB\n",
565566
(void *)orig_ip);

include/linux/objtool.h

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,55 @@
22
#ifndef _LINUX_OBJTOOL_H
33
#define _LINUX_OBJTOOL_H
44

5+
#ifndef __ASSEMBLY__
6+
7+
#include <linux/types.h>
8+
9+
/*
10+
* This struct is used by asm and inline asm code to manually annotate the
11+
* location of registers on the stack.
12+
*/
13+
struct unwind_hint {
14+
u32 ip;
15+
s16 sp_offset;
16+
u8 sp_reg;
17+
u8 type;
18+
u8 end;
19+
};
20+
#endif
21+
22+
/*
23+
* UNWIND_HINT_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP
24+
* (the caller's SP right before it made the call). Used for all callable
25+
* functions, i.e. all C code and all callable asm functions.
26+
*
27+
* UNWIND_HINT_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset
28+
* points to a fully populated pt_regs from a syscall, interrupt, or exception.
29+
*
30+
* UNWIND_HINT_TYPE_REGS_PARTIAL: Used in entry code to indicate that
31+
* sp_reg+sp_offset points to the iret return frame.
32+
*/
33+
#define UNWIND_HINT_TYPE_CALL 0
34+
#define UNWIND_HINT_TYPE_REGS 1
35+
#define UNWIND_HINT_TYPE_REGS_PARTIAL 2
36+
#define UNWIND_HINT_TYPE_RET_OFFSET 3
37+
538
#ifdef CONFIG_STACK_VALIDATION
639

740
#ifndef __ASSEMBLY__
41+
42+
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
43+
"987: \n\t" \
44+
".pushsection .discard.unwind_hints\n\t" \
45+
/* struct unwind_hint */ \
46+
".long 987b - .\n\t" \
47+
".short " __stringify(sp_offset) "\n\t" \
48+
".byte " __stringify(sp_reg) "\n\t" \
49+
".byte " __stringify(type) "\n\t" \
50+
".byte " __stringify(end) "\n\t" \
51+
".balign 4 \n\t" \
52+
".popsection\n\t"
53+
854
/*
955
* This macro marks the given function's stack frame as "non-standard", which
1056
* tells objtool to ignore the function when doing stack metadata validation.
@@ -29,12 +75,54 @@
2975
.long 999b; \
3076
.popsection;
3177

78+
/*
79+
* In asm, there are two kinds of code: normal C-type callable functions and
80+
* the rest. The normal callable functions can be called by other code, and
81+
* don't do anything unusual with the stack. Such normal callable functions
82+
* are annotated with the ENTRY/ENDPROC macros. Most asm code falls in this
83+
* category. In this case, no special debugging annotations are needed because
84+
* objtool can automatically generate the ORC data for the ORC unwinder to read
85+
* at runtime.
86+
*
87+
* Anything which doesn't fall into the above category, such as syscall and
88+
* interrupt handlers, tends to not be called directly by other functions, and
89+
* often does unusual non-C-function-type things with the stack pointer. Such
90+
* code needs to be annotated such that objtool can understand it. The
91+
* following CFI hint macros are for this type of code.
92+
*
93+
* These macros provide hints to objtool about the state of the stack at each
94+
* instruction. Objtool starts from the hints and follows the code flow,
95+
* making automatic CFI adjustments when it sees pushes and pops, filling out
96+
* the debuginfo as necessary. It will also warn if it sees any
97+
* inconsistencies.
98+
*/
99+
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
100+
.Lunwind_hint_ip_\@:
101+
.pushsection .discard.unwind_hints
102+
/* struct unwind_hint */
103+
.long .Lunwind_hint_ip_\@ - .
104+
.short \sp_offset
105+
.byte \sp_reg
106+
.byte \type
107+
.byte \end
108+
.balign 4
109+
.popsection
110+
.endm
111+
32112
#endif /* __ASSEMBLY__ */
33113

34114
#else /* !CONFIG_STACK_VALIDATION */
35115

116+
#ifndef __ASSEMBLY__
117+
118+
#define UNWIND_HINT(sp_reg, sp_offset, type, end) \
119+
"\n\t"
36120
#define STACK_FRAME_NON_STANDARD(func)
121+
#else
37122
#define ANNOTATE_INTRA_FUNCTION_CALL
123+
.macro UNWIND_HINT sp_reg:req sp_offset=0 type:req end=0
124+
.endm
125+
#endif
38126

39127
#endif /* CONFIG_STACK_VALIDATION */
40128

tools/arch/x86/include/asm/orc_types.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,6 @@
3939
#define ORC_REG_SP_INDIRECT 9
4040
#define ORC_REG_MAX 15
4141

42-
/*
43-
* ORC_TYPE_CALL: Indicates that sp_reg+sp_offset resolves to PREV_SP (the
44-
* caller's SP right before it made the call). Used for all callable
45-
* functions, i.e. all C code and all callable asm functions.
46-
*
47-
* ORC_TYPE_REGS: Used in entry code to indicate that sp_reg+sp_offset points
48-
* to a fully populated pt_regs from a syscall, interrupt, or exception.
49-
*
50-
* ORC_TYPE_REGS_IRET: Used in entry code to indicate that sp_reg+sp_offset
51-
* points to the iret return frame.
52-
*
53-
* The UNWIND_HINT macros are used only for the unwind_hint struct. They
54-
* aren't used in struct orc_entry due to size and complexity constraints.
55-
* Objtool converts them to real types when it converts the hints to orc
56-
* entries.
57-
*/
58-
#define ORC_TYPE_CALL 0
59-
#define ORC_TYPE_REGS 1
60-
#define ORC_TYPE_REGS_IRET 2
61-
#define UNWIND_HINT_TYPE_RET_OFFSET 3
62-
6342
#ifndef __ASSEMBLY__
6443
/*
6544
* This struct is more or less a vastly simplified version of the DWARF Call
@@ -78,19 +57,6 @@ struct orc_entry {
7857
unsigned end:1;
7958
} __packed;
8059

81-
/*
82-
* This struct is used by asm and inline asm code to manually annotate the
83-
* location of registers on the stack for the ORC unwinder.
84-
*
85-
* Type can be either ORC_TYPE_* or UNWIND_HINT_TYPE_*.
86-
*/
87-
struct unwind_hint {
88-
u32 ip;
89-
s16 sp_offset;
90-
u8 sp_reg;
91-
u8 type;
92-
u8 end;
93-
};
9460
#endif /* __ASSEMBLY__ */
9561

9662
#endif /* _ORC_TYPES_H */

0 commit comments

Comments
 (0)