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