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, &notes_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
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to