libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [PATCH 4/4] Add support for multiple threads in core f


From: Alexander Larsson
Subject: [Libunwind-devel] [PATCH 4/4] Add support for multiple threads in core files
Date: Fri, 23 Mar 2012 21:00:30 +0100

_UCD_select_thread() lets you select the active thread from
the core file and _UCD_get_num_threads() tells you how many there are.
---
 include/libunwind-coredump.h |    2 +
 src/coredump/_UCD_create.c   |   83 ++++++++++++++++++++++++++++--------------
 src/coredump/_UCD_internal.h |    2 +
 3 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/include/libunwind-coredump.h b/include/libunwind-coredump.h
index a44536f..d2b05e7 100644
--- a/include/libunwind-coredump.h
+++ b/include/libunwind-coredump.h
@@ -40,6 +40,8 @@ struct UCD_info;
 extern struct UCD_info *_UCD_create(const char *filename);
 extern void _UCD_destroy(struct UCD_info *);
 
+extern int _UCD_get_num_threads(struct UCD_info *);
+extern void _UCD_select_thread(struct UCD_info *, int);
 extern pid_t _UCD_get_pid(struct UCD_info *);
 extern int _UCD_get_cursig(struct UCD_info *);
 extern int _UCD_add_backing_file_at_segment(struct UCD_info *, int phdr_no, 
const char *filename);
diff --git a/src/coredump/_UCD_create.c b/src/coredump/_UCD_create.c
index ec0dfb5..02df5e5 100644
--- a/src/coredump/_UCD_create.c
+++ b/src/coredump/_UCD_create.c
@@ -206,6 +206,9 @@ _UCD_create(const char *filename)
        Debug(2, "phdr[%03d]: type:%d", i, cur->p_type);
        if (cur->p_type == PT_NOTE)
          {
+           unsigned char *p, *note_end;
+           unsigned n_threads;
+
            ui->note_phdr = malloc(cur->p_filesz);
            if (lseek(fd, cur->p_offset, SEEK_SET) != (off_t)cur->p_offset
             || (uoff_t)read(fd, ui->note_phdr, cur->p_filesz) != cur->p_filesz
@@ -215,33 +218,46 @@ _UCD_create(const char *filename)
                goto err;
              }
 
-           /* Note is three 32-bit words: */
-           /* Elf32_Word n_namesz; Length of the note's name */
-           /* Elf32_Word n_descsz; Length of the note's descriptor */
-           /* Elf32_Word n_type;   Type */
-           /* followed by name (padded to 32 bits(?)) and then descr */
-           Elf32_Nhdr *note_hdr = ui->note_phdr;
-           if (cur->p_filesz >= 3*4
-            && note_hdr->n_type == NT_PRSTATUS
-            && cur->p_filesz >= (3*4 + note_hdr->n_namesz + note_hdr->n_descsz 
+ sizeof(*ui->prstatus))
-           )
+           note_end = (unsigned char *)ui->note_phdr + cur->p_filesz;
+
+           /* Count number of threads */
+           n_threads = 0;
+           p = ui->note_phdr;
+           while (p + sizeof (Elf32_Nhdr) <= note_end)
              {
-               ui->prstatus = (void*) ((((long)note_hdr + sizeof(*note_hdr) + 
note_hdr->n_namesz) + 3) & ~3L);
-#if 0
-               printf("pid:%d\n", ui->prstatus->pr_pid);
-               printf("ebx:%ld\n", (long)ui->prstatus->pr_reg[0]);
-               printf("ecx:%ld\n", (long)ui->prstatus->pr_reg[1]);
-               printf("edx:%ld\n", (long)ui->prstatus->pr_reg[2]);
-               printf("esi:%ld\n", (long)ui->prstatus->pr_reg[3]);
-               printf("edi:%ld\n", (long)ui->prstatus->pr_reg[4]);
-               printf("ebp:%ld\n", (long)ui->prstatus->pr_reg[5]);
-               printf("eax:%ld\n", (long)ui->prstatus->pr_reg[6]);
-               printf("xds:%ld\n", (long)ui->prstatus->pr_reg[7]);
-               printf("xes:%ld\n", (long)ui->prstatus->pr_reg[8]);
-               printf("xfs:%ld\n", (long)ui->prstatus->pr_reg[9]);
-               printf("xgs:%ld\n", (long)ui->prstatus->pr_reg[10]);
-               printf("orig_eax:%ld\n", (long)ui->prstatus->pr_reg[11]);
-#endif
+               Elf32_Nhdr *note_hdr = (Elf32_Nhdr *)p;
+               unsigned char *p_next;
+
+               p_next = p + sizeof (Elf32_Nhdr) + ((note_hdr->n_namesz + 3) & 
~3L) + note_hdr->n_descsz;
+
+               if (p_next >= note_end)
+                 break;
+
+               if (note_hdr->n_type == NT_PRSTATUS)
+                 n_threads++;
+
+               p = p_next;
+             }
+
+           ui->n_threads = n_threads;
+           ui->threads = malloc(sizeof (void *) * n_threads);
+
+           n_threads = 0;
+           p = ui->note_phdr;
+           while (p + sizeof (Elf32_Nhdr) <= note_end)
+             {
+               Elf32_Nhdr *note_hdr = (Elf32_Nhdr *)p;
+               unsigned char *p_next;
+
+               p_next = p + sizeof (Elf32_Nhdr) + ((note_hdr->n_namesz + 3) & 
~3L) + note_hdr->n_descsz;
+
+               if (p_next >= note_end)
+                 break;
+
+               if (note_hdr->n_type == NT_PRSTATUS)
+                 ui->threads[n_threads++] = (void*) ((((long)note_hdr + 
sizeof(*note_hdr) + note_hdr->n_namesz) + 3) & ~3L);
+
+               p = p_next;
              }
          }
        if (cur->p_type == PT_LOAD)
@@ -263,12 +279,14 @@ _UCD_create(const char *filename)
        cur++;
       }
 
-    if (!ui->prstatus)
+    if (ui->n_threads == 0)
       {
        Debug(0, "No NT_PRSTATUS note found in '%s'\n", filename);
        goto err;
       }
 
+    ui->prstatus = ui->threads[0];
+
   return ui;
 
  err:
@@ -276,6 +294,17 @@ _UCD_create(const char *filename)
   return NULL;
 }
 
+int _UCD_get_num_threads(struct UCD_info *ui)
+{
+  return ui->n_threads;
+}
+
+void _UCD_select_thread(struct UCD_info *ui, int n)
+{
+  if (n >= 0 && n < ui->n_threads)
+    ui->prstatus = ui->threads[n];
+}
+
 pid_t _UCD_get_pid(struct UCD_info *ui)
 {
   return ui->prstatus->pr_pid;
diff --git a/src/coredump/_UCD_internal.h b/src/coredump/_UCD_internal.h
index ecad0bd..8b36729 100644
--- a/src/coredump/_UCD_internal.h
+++ b/src/coredump/_UCD_internal.h
@@ -91,6 +91,8 @@ struct UCD_info
     unsigned phdrs_count;
     void *note_phdr; /* allocated or NULL */
     struct PRSTATUS_STRUCT *prstatus; /* points inside note_phdr */
+    int n_threads;
+    struct PRSTATUS_STRUCT **threads;
 
     struct elf_dyn_info edi;
   };
-- 
1.7.7.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]