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; }; -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility