32-bit ARM kernels built with the Thumb-2 instruction set utilize

the R7 register instead of FP for unwinding stacks using the DWARF
unwinder.  On those kernels, without the patch, the "bt" command
only shows the task header.
(vincent.whitchurch@axis.com)
This commit is contained in:
Dave Anderson 2019-02-26 10:13:59 -05:00
parent 5aa3c1da3e
commit 8e21aa3fa5
4 changed files with 24 additions and 8 deletions

15
arm.c
View File

@ -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;
}

1
defs.h
View File

@ -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 */

View File

@ -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",

View File

@ -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]);