Skip to content

Commit 18636af

Browse files
carlocaionecarlescufi
authored andcommitted
arm64: Add frame-pointer based stack unwinding
Add the frame-pointer based stack unwinding on ARM64. This is a typical output with the feature enabled: *** Booting Zephyr OS build zephyr-v3.4.0-1029-gae22ff648c16 *** E: ELR_ELn: 0x00000000400011c8 E: ESR_ELn: 0x0000000096000046 E: EC: 0x25 (Data Abort taken without a change in Exception level) E: IL: 0x1 E: ISS: 0x46 E: FAR_ELn: 0x0000000000000000 E: TPIDRRO: 0x0100000040011650 E: x0: 0x0000000000000000 x1: 0x0000000000000003 E: x2: 0x0000000000000003 x3: 0x000000004005c6a0 E: x4: 0x0000000000000000 x5: 0x000000004005c7f0 E: x6: 0x0000000048000000 x7: 0x0000000048000000 E: x8: 0x0000000000000005 x9: 0x0000000000000000 E: x10: 0x0000000000000000 x11: 0x0000000000000000 E: x12: 0x0000000000000000 x13: 0x0000000000000000 E: x14: 0x0000000000000000 x15: 0x0000000000000000 E: x16: 0x0000000040004290 x17: 0x0000000000000000 E: x18: 0x0000000000000000 lr: 0x0000000040001208 E: E: backtrace 0: fp: 0x000000004005c690 lr: 0x0000000040001270 E: backtrace 1: fp: 0x000000004005c6b0 lr: 0x0000000040001290 E: backtrace 2: fp: 0x000000004005c7d0 lr: 0x0000000040004ac0 E: backtrace 3: fp: 0x000000004005c7f0 lr: 0x00000000400013a4 E: backtrace 4: fp: 0x000000004005c800 lr: 0x0000000000000000 E: E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 E: Current thread: 0x40011310 (unknown) E: Halting system Signed-off-by: Carlo Caione <[email protected]>
1 parent 04e0e45 commit 18636af

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

arch/arm64/core/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ config ARM64_SAFE_EXCEPTION_STACK
128128
used for user stack overflow checking, because kernel stack support
129129
the checking work.
130130

131+
config ARM64_ENABLE_FRAME_POINTER
132+
bool
133+
default y
134+
depends on OVERRIDE_FRAME_POINTER_DEFAULT && !OMIT_FRAME_POINTER
135+
help
136+
Hidden option to simplify access to OVERRIDE_FRAME_POINTER_DEFAULT
137+
and OMIT_FRAME_POINTER. It is automatically enabled when the frame
138+
pointer unwinding is enabled.
139+
131140
config ARM64_SAFE_EXCEPTION_STACK_SIZE
132141
int "The stack size of the safe exception stack"
133142
default 4096

arch/arm64/core/fatal.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,45 @@ static void esf_dump(const z_arch_esf_t *esf)
191191
LOG_ERR("x16: 0x%016llx x17: 0x%016llx", esf->x16, esf->x17);
192192
LOG_ERR("x18: 0x%016llx lr: 0x%016llx", esf->x18, esf->lr);
193193
}
194+
195+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
196+
static void esf_unwind(const z_arch_esf_t *esf)
197+
{
198+
/*
199+
* For GCC:
200+
*
201+
* ^ +-----------------+
202+
* | | |
203+
* | | |
204+
* | | |
205+
* | | |
206+
* | | function stack |
207+
* | | |
208+
* | | |
209+
* | | |
210+
* | | |
211+
* | +-----------------+
212+
* | | LR |
213+
* | +-----------------+
214+
* | | previous FP | <---+ FP
215+
* + +-----------------+
216+
*/
217+
218+
uint64_t *fp = (uint64_t *) esf->fp;
219+
unsigned int count = 0;
220+
uint64_t lr;
221+
222+
LOG_ERR("");
223+
while (fp != NULL) {
224+
lr = fp[1];
225+
LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx",
226+
count++, (uint64_t) fp, lr);
227+
fp = (uint64_t *) fp[0];
228+
}
229+
LOG_ERR("");
230+
}
231+
#endif
232+
194233
#endif /* CONFIG_EXCEPTION_DEBUG */
195234

196235
static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far,
@@ -261,6 +300,10 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf)
261300
if (esf != NULL) {
262301
esf_dump(esf);
263302
}
303+
304+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
305+
esf_unwind(esf);
306+
#endif /* CONFIG_ARM64_ENABLE_FRAME_POINTER */
264307
#endif /* CONFIG_EXCEPTION_DEBUG */
265308

266309
z_fatal_error(reason, esf);

arch/arm64/core/offsets/offsets.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ GEN_NAMED_OFFSET_SYM(_callee_saved_t, x27, x27_x28);
4040
GEN_NAMED_OFFSET_SYM(_callee_saved_t, x29, x29_sp_el0);
4141
GEN_NAMED_OFFSET_SYM(_callee_saved_t, sp_elx, sp_elx_lr);
4242

43+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
44+
GEN_NAMED_OFFSET_SYM(_esf_t, fp, fp);
45+
#endif
46+
4347
GEN_NAMED_OFFSET_SYM(_esf_t, spsr, spsr_elr);
4448
GEN_NAMED_OFFSET_SYM(_esf_t, x18, x18_lr);
4549
GEN_NAMED_OFFSET_SYM(_esf_t, x16, x16_x17);

arch/arm64/core/vector_table.S

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ _ASM_FILE_PROLOGUE
7272
.endif
7373
#endif
7474

75+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
76+
str x29, [sp, ___esf_t_fp_OFFSET]
77+
#endif
78+
7579
mrs \xreg0, spsr_el1
7680
mrs \xreg1, elr_el1
7781
stp \xreg0, \xreg1, [sp, ___esf_t_spsr_elr_OFFSET]
@@ -335,6 +339,10 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc)
335339
ldp x16, x17, [sp, ___esf_t_x16_x17_OFFSET]
336340
ldp x18, lr, [sp, ___esf_t_x18_lr_OFFSET]
337341

342+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
343+
ldr x29, [sp, ___esf_t_fp_OFFSET]
344+
#endif
345+
338346
add sp, sp, ___esf_t_SIZEOF
339347

340348
/*

include/zephyr/arch/arm64/exc.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ struct __esf {
4747
uint64_t lr;
4848
uint64_t spsr;
4949
uint64_t elr;
50+
#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER
51+
uint64_t fp;
52+
#endif
5053
#ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK
5154
uint64_t sp;
5255
#endif
53-
} __aligned(16);
56+
} __packed __aligned(16);
5457

5558
typedef struct __esf z_arch_esf_t;
5659

0 commit comments

Comments
 (0)