KDUMP, NETDUMP and DISKDUMP all saves register values for active tasks onto
exception frame at kernel crash. This patch implements the logic to collect the
register values by retrieving EFRAME information from back_trace()'s output.
Signed-off-by: HATAYAMA Daisuke <d.hatayama(a)jp.fujitsu.com>
---
src/libgcore/gcore_x86.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 67 insertions(+), 0 deletions(-)
diff --git a/src/libgcore/gcore_x86.c b/src/libgcore/gcore_x86.c
index 377df6d..29fe808 100644
--- a/src/libgcore/gcore_x86.c
+++ b/src/libgcore/gcore_x86.c
@@ -1354,6 +1354,64 @@ static ulong gcore_x86_64_get_cpu__pda_oldrsp(int cpu)
return oldrsp;
}
+static int
+gcore_find_regs_from_bt_output(FILE *output, char *buf, size_t bufsize)
+{
+ while (fgets(buf, bufsize, output))
+ if (strncmp(buf, " RIP:", 8) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static int
+gcore_get_regs_from_bt_output(FILE *output, struct pt_regs *regs)
+{
+ char buf[BUFSIZE];
+
+ if (gcore_find_regs_from_bt_output(output, buf, BUFSIZE) == FALSE)
+ return FALSE;
+
+ sscanf(buf, " RIP: %016lx RSP: %016lx RFLAGS: %08lx\n",
+ ®s->rip, ®s->rsp, ®s->eflags);
+ fscanf(output, " RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ ®s->rax, ®s->rbx, ®s->rcx);
+ fscanf(output, " RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ ®s->rdx, ®s->rsi, ®s->rdi);
+ fscanf(output, " RBP: %016lx R8: %016lx R9: %016lx\n",
+ ®s->rbp, ®s->r8, ®s->r9);
+ fscanf(output, " R10: %016lx R11: %016lx R12: %016lx\n",
+ ®s->r10, ®s->r11, ®s->r12);
+ fscanf(output, " R13: %016lx R14: %016lx R15: %016lx\n",
+ ®s->r13, ®s->r14, ®s->r15);
+ fscanf(output, " ORIG_RAX: %016lx CS: %04lx SS: %04lx\n",
+ ®s->orig_rax, ®s->cs, ®s->ss);
+
+ return TRUE;
+}
+
+static int
+gcore_get_regs_from_eframe(struct task_context *tc, struct pt_regs *regs)
+{
+ int ret;
+ struct bt_info bt;
+
+ BZERO(&bt, sizeof(struct bt_info));
+ bt.stackbuf = NULL;
+ bt.tc = tc;
+ bt.task = tc->task;
+ bt.stackbase = GET_STACKBASE(tc->task);
+ bt.stacktop = GET_STACKTOP(tc->task);
+
+ open_tmpfile();
+ back_trace(&bt);
+ rewind(pc->tmpfile);
+ ret = gcore_get_regs_from_bt_output(pc->tmpfile, regs);
+ close_tmpfile();
+
+ return ret;
+}
+
static int get_active_regs(struct task_context *target,
struct user_regs_struct *regs)
{
@@ -1363,6 +1421,15 @@ static int get_active_regs(struct task_context *target,
return TRUE;
}
+ if (gcore_get_regs_from_eframe(target, (struct pt_regs *)regs)) {
+ /*
+ * EFRAME contains CS and SS only. Here collects the
+ * remaining part of segment registers.
+ */
+ restore_segment_registers(target->task, regs);
+ return TRUE;
+ }
+
return FALSE;
}
--
1.7.4