[Crash-utility] [PATCH] ARM: Fix idle task stack unwinding on Thumb-2 kernels
Dave Anderson
anderson at redhat.com
Tue Feb 26 15:17:51 UTC 2019
----- Original Message -----
> 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>]
Queued for crash-7.2.6:
https://github.com/crash-utility/crash/commit/8e21aa3fa5c255396e9dce49786eae595f0371c1
Thanks,
Dave
>
> 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
More information about the Crash-utility
mailing list