ARM kernels built with the Thumb-2 instruction need R7 instead of FP for unwinding stacks using the DWARF unwinder. On a Thumb-2 kernel: Before: crash> bt 1 PID: 1 TASK: ee7e0000 CPU: 1 COMMAND: "systemd-shutdow" After: crash> bt 1 PID: 1 TASK: ee7e0000 CPU: 1 COMMAND: "systemd-shutdow" #0 [<805587a1>] (__schedule) from [<80558d2b>] #1 [<80558d2b>] (schedule) from [<8055c8bb>] #2 [<8055c8bb>] (schedule_hrtimeout_range_clock) from [<8055c937>] #3 [<8055c937>] (schedule_hrtimeout_range) from [<8012cbdf>] #4 [<8012cbdf>] (sys_rt_sigtimedwait) from [<80107259>] Change-Id: Iec0c3a3ab089441d0ebf0002343790d65fe6ca78 --- arm.c | 15 +++++++++++---- defs.h | 1 + symbols.c | 2 ++ unwind_arm.c | 14 ++++++++++---- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/arm.c b/arm.c index 9652361..b05b0b3 100644 --- a/arm.c +++ b/arm.c @@ -301,6 +301,8 @@ arm_init(int when) * thread_info.cpu_context. */ STRUCT_SIZE_INIT(cpu_context_save, "cpu_context_save"); + MEMBER_OFFSET_INIT(cpu_context_save_r7, + "cpu_context_save", "r7"); MEMBER_OFFSET_INIT(cpu_context_save_fp, "cpu_context_save", "fp"); MEMBER_OFFSET_INIT(cpu_context_save_sp, @@ -1313,13 +1315,18 @@ arm_get_frame(struct bt_info *bt, ulong *pcp, ulong *spp) cpu_context = tt->thread_info + OFFSET(thread_info_cpu_context); #define GET_REG(ptr, cp, off) ((*ptr) = (*((ulong *)((cp) + OFFSET(off))))) - /* - * Unwinding code needs FP value also so we pass it with bt. - */ - GET_REG(&bt->frameptr, cpu_context, cpu_context_save_fp); GET_REG(spp, cpu_context, cpu_context_save_sp); GET_REG(pcp, cpu_context, cpu_context_save_pc); + /* + * Unwinding code needs FP (R7 for Thumb code) value also so we pass it + * with bt. + */ + if (*pcp & 1) + GET_REG(&bt->frameptr, cpu_context, cpu_context_save_r7); + else + GET_REG(&bt->frameptr, cpu_context, cpu_context_save_fp); + return TRUE; } diff --git a/defs.h b/defs.h index 5841b1f..b4f6372 100644 --- a/defs.h +++ b/defs.h @@ -2066,6 +2066,7 @@ struct offset_table { /* stash of commonly-used offsets */ long xa_node_shift; long hd_struct_dkstats; long disk_stats_in_flight; + long cpu_context_save_r7; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/symbols.c b/symbols.c index e73e735..31a4d7b 100644 --- a/symbols.c +++ b/symbols.c @@ -10047,6 +10047,8 @@ dump_offset_table(char *spec, ulong makestruct) fprintf(fp, " s390_stack_frame_r14: %ld\n", OFFSET(s390_stack_frame_r14)); + fprintf(fp, " cpu_context_save_r7: %ld\n", + OFFSET(cpu_context_save_r7)); fprintf(fp, " cpu_context_save_fp: %ld\n", OFFSET(cpu_context_save_fp)); fprintf(fp, " cpu_context_save_sp: %ld\n", diff --git a/unwind_arm.c b/unwind_arm.c index 8667d3c..1a8f51e 100644 --- a/unwind_arm.c +++ b/unwind_arm.c @@ -87,6 +87,7 @@ struct stackframe { }; enum regs { + R7 = 7, FP = 11, SP = 13, LR = 14, @@ -615,6 +616,7 @@ unwind_frame(struct stackframe *frame, ulong stacktop) struct unwind_ctrl_block ctrl; struct unwind_idx *idx; ulong low, high; + int fpindex = FP; low = frame->sp; high = stacktop; @@ -622,6 +624,10 @@ unwind_frame(struct stackframe *frame, ulong stacktop) if (!is_kernel_text(frame->pc)) return FALSE; + /* Thumb needs R7 instead of FP */ + if (frame->pc & 1) + fpindex = R7; + tbl = search_table(frame->pc); if (!tbl) { error(WARNING, "UNWIND: cannot find unwind table for %lx\n", @@ -630,13 +636,13 @@ unwind_frame(struct stackframe *frame, ulong stacktop) } idx = search_index(tbl, frame->pc); - ctrl.vrs[FP] = frame->fp; + ctrl.vrs[fpindex] = frame->fp; ctrl.vrs[SP] = frame->sp; ctrl.vrs[LR] = frame->lr; ctrl.vrs[PC] = 0; if (CRASHDEBUG(5)) { - fprintf(fp, "UNWIND: >frame: FP=%lx\n", ctrl.vrs[FP]); + fprintf(fp, "UNWIND: >frame: FP=%lx\n", ctrl.vrs[fpindex]); fprintf(fp, "UNWIND: >frame: SP=%lx\n", ctrl.vrs[SP]); fprintf(fp, "UNWIND: >frame: LR=%lx\n", ctrl.vrs[LR]); fprintf(fp, "UNWIND: >frame: PC=%lx\n", ctrl.vrs[PC]); @@ -706,13 +712,13 @@ unwind_frame(struct stackframe *frame, ulong stacktop) if (frame->pc == ctrl.vrs[PC]) return FALSE; - frame->fp = ctrl.vrs[FP]; + frame->fp = ctrl.vrs[fpindex]; frame->sp = ctrl.vrs[SP]; frame->lr = ctrl.vrs[LR]; frame->pc = ctrl.vrs[PC]; if (CRASHDEBUG(5)) { - fprintf(fp, "UNWIND: <frame: FP=%lx\n", ctrl.vrs[FP]); + fprintf(fp, "UNWIND: <frame: FP=%lx\n", ctrl.vrs[fpindex]); fprintf(fp, "UNWIND: <frame: SP=%lx\n", ctrl.vrs[SP]); fprintf(fp, "UNWIND: <frame: LR=%lx\n", ctrl.vrs[LR]); fprintf(fp, "UNWIND: <frame: PC=%lx\n", ctrl.vrs[PC]); -- 2.20.0 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility