Hi Dave and Mika,
Thanks for your input. Here's attempt number two. I have:
- eliminated the leaks
- removed 'crash_task_pid'
- fixed the formatting
- not used gmail, since it corrupts the patch
- used malloc/free for panic_task_regs
Regards,
Per
diff --git a/arm.c b/arm.c
index 06b2f1c..b3841c0 100644
--- a/arm.c
+++ b/arm.c
@@ -73,7 +73,7 @@ struct arm_cpu_context_save {
/*
* Holds registers during the crash.
*/
-static struct arm_pt_regs panic_task_regs;
+static struct arm_pt_regs *panic_task_regs;
#define PGDIR_SIZE() (4 * PAGESIZE())
#define PGDIR_OFFSET(X) (((ulong)(X)) & (PGDIR_SIZE() - 1))
@@ -392,7 +392,6 @@ arm_dump_machdep_table(ulong arg)
fprintf(fp, " kernel_text_end: %lx\n", ms->kernel_text_end);
fprintf(fp, "exception_text_start: %lx\n", ms->exception_text_start);
fprintf(fp, " exception_text_end: %lx\n", ms->exception_text_end);
- fprintf(fp, " crash_task_pid: %ld\n", ms->crash_task_pid);
fprintf(fp, " crash_task_regs: %lx\n", (ulong)ms->crash_task_regs);
}
@@ -484,71 +483,104 @@ arm_get_crash_notes(void)
Elf32_Nhdr *note;
ulong ptr, offset;
char *buf, *p;
+ ulong *notes_ptrs;
+ ulong per_cpu_offsets_addr;
+ ulong *per_cpu_offsets;
+ ulong i;
if (!symbol_exists("crash_notes"))
return FALSE;
crash_notes = symbol_value("crash_notes");
- if (kt->cpus > 1)
- error(WARNING, "only one CPU is currently supported\n");
+ notes_ptrs = GETBUF(kt->cpus*sizeof(notes_ptrs[0]));
/*
* Read crash_notes for the first CPU. crash_notes are in standard ELF
* note format.
*/
- if (!readmem(crash_notes, KVADDR, &ptr, sizeof(ptr), "crash_notes",
+ if (!readmem(crash_notes, KVADDR, ¬es_ptrs[kt->cpus-1],
sizeof(notes_ptrs[kt->cpus-1]), "crash_notes",
RETURN_ON_ERROR)) {
error(WARNING, "cannot read crash_notes\n");
+ FREEBUF(notes_ptrs);
return FALSE;
}
+
+
+ if (symbol_exists("__per_cpu_offset")) {
+
+ /* Get the __per_cpu_offset array */
+ per_cpu_offsets_addr = symbol_value("__per_cpu_offset");
+
+ per_cpu_offsets = GETBUF(kt->cpus*sizeof(*per_cpu_offsets));
+
+ if (!readmem(per_cpu_offsets_addr, KVADDR, per_cpu_offsets,
kt->cpus*sizeof(*per_cpu_offsets), "per_cpu_offsets",
+ RETURN_ON_ERROR)) {
+ error(WARNING, "cannot read per_cpu_offsets\n");
+ FREEBUF(per_cpu_offsets);
+ return FALSE;
+ }
+
+ /* Add __per_cpu_offset for each cpu to form the pointer to the notes */
+ for (i = 0; i<kt->cpus; i++) {
+ notes_ptrs[i] = notes_ptrs[kt->cpus-1] + per_cpu_offsets[i];
+ }
+ FREEBUF(per_cpu_offsets);
+ }
buf = GETBUF(SIZE(note_buf));
+ panic_task_regs = malloc(kt->cpus*sizeof(*panic_task_regs));
+
+ for (i=0;i<kt->cpus;i++) {
+
+ if (!readmem(notes_ptrs[i], KVADDR, buf, SIZE(note_buf), "note_buf_t",
+ RETURN_ON_ERROR)) {
+ error(WARNING, "failed to read note_buf_t\n");
+ goto fail;
+ }
- if (!readmem(ptr, KVADDR, buf, SIZE(note_buf), "note_buf_t",
- RETURN_ON_ERROR)) {
- error(WARNING, "failed to read note_buf_t\n");
- goto fail;
- }
+ /*
+ * Do some sanity checks for this note before reading registers from it.
+ */
+ note = (Elf32_Nhdr *)buf;
+ p = buf + sizeof(Elf32_Nhdr);
- /*
- * Do some sanity checks for this note before reading registers from it.
- */
- note = (Elf32_Nhdr *)buf;
- p = buf + sizeof(Elf32_Nhdr);
+ if (note->n_type != NT_PRSTATUS) {
+ error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n");
+ goto fail;
+ }
+ if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] !=
'E') {
+ error(WARNING, "invalid note (name != \"CORE\"\n");
+ goto fail;
+ }
- if (note->n_type != NT_PRSTATUS) {
- error(WARNING, "invalid note (n_type != NT_PRSTATUS)\n");
- goto fail;
- }
- if (p[0] != 'C' || p[1] != 'O' || p[2] != 'R' || p[3] !=
'E') {
- error(WARNING, "invalid note (name != \"CORE\"\n");
- goto fail;
- }
+ /*
+ * Find correct location of note data. This contains elf_prstatus
+ * structure which has registers etc. for the crashed task.
+ */
+ offset = sizeof(Elf32_Nhdr);
+ offset = roundup(offset + note->n_namesz, 4);
+ p = buf + offset; /* start of elf_prstatus */
- /*
- * Find correct location of note data. This contains elf_prstatus
- * structure which has registers etc. for the crashed task.
- */
- offset = sizeof(Elf32_Nhdr);
- offset = roundup(offset + note->n_namesz, 4);
- p = buf + offset; /* start of elf_prstatus */
+ BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs[i],
+ sizeof(panic_task_regs[i]));
- BCOPY(p + OFFSET(elf_prstatus_pr_reg), &panic_task_regs,
- sizeof(panic_task_regs));
+ }
/*
- * And finally we have pid and registers for the crashed task. This is
+ * And finally we have the registers for the crashed task. This is
* used later on when dumping backtrace.
*/
- ms->crash_task_pid = *(ulong *)(p + OFFSET(elf_prstatus_pr_pid));
- ms->crash_task_regs = &panic_task_regs;
+ ms->crash_task_regs = panic_task_regs;
FREEBUF(buf);
+ FREEBUF(notes_ptrs);
return TRUE;
fail:
FREEBUF(buf);
+ FREEBUF(notes_ptrs);
+ free(panic_task_regs);
return FALSE;
}
@@ -996,20 +1028,20 @@ arm_get_dumpfile_stack_frame(struct bt_info *bt, ulong *nip, ulong
*ksp)
if (!ms->crash_task_regs)
return FALSE;
- if (tt->panic_task != bt->task || bt->tc->pid != ms->crash_task_pid)
+ if (!is_task_active(bt->task))
return FALSE;
-
+
/*
* We got registers for panic task from crash_notes. Just return them.
*/
- *nip = ms->crash_task_regs->ARM_pc;
- *ksp = ms->crash_task_regs->ARM_sp;
+ *nip = ms->crash_task_regs[bt->tc->processor].ARM_pc;
+ *ksp = ms->crash_task_regs[bt->tc->processor].ARM_sp;
/*
* Also store pointer to all registers in case unwinding code needs
* to access LR.
*/
- bt->machdep = ms->crash_task_regs;
+ bt->machdep = &(ms->crash_task_regs[bt->tc->processor]);
return TRUE;
}
diff --git a/defs.h b/defs.h
index d431d6e..6e0c8cc 100755
--- a/defs.h
+++ b/defs.h
@@ -85,7 +85,7 @@
#define NR_CPUS (64)
#endif
#ifdef ARM
-#define NR_CPUS (1)
+#define NR_CPUS (4)
#endif
#define BUFSIZE (1500)
@@ -4062,7 +4062,6 @@ struct machine_specific {
ulong kernel_text_end;
ulong exception_text_start;
ulong exception_text_end;
- ulong crash_task_pid;
struct arm_pt_regs *crash_task_regs;
};