[Top][All Lists]
[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