summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeng Fan <van.freenix@gmail.com>2013-09-05 13:05:17 +0800
committerPeng Fan <van.freenix@gmail.com>2013-09-05 13:47:39 +0800
commita48d508e21d4baa3e7c395218a3bce5ad2359d96 (patch)
tree1c23d06a17c09fe5db4f9d1d82ff6a6694ae3ad9
parent65096e5cf330be0eaed449c5ec44afb50225e41f (diff)
file details and debug support
This patch contains the file details part and linkmap support. In order to save space, the linkmap part and file details part are merged into one implementation. Both use the same pointer, obj->detail. Signed-off-by: Peng Fan <van.freenix@gmail.com>
-rw-r--r--libbsd/include/link_elf.h50
-rw-r--r--rtl-debugger.c53
-rw-r--r--rtl-obj.c11
-rw-r--r--rtl-obj.h7
-rw-r--r--rtl-rap.c140
-rw-r--r--rtl-trace.c3
-rw-r--r--rtl-trace.h1
7 files changed, 249 insertions, 16 deletions
diff --git a/libbsd/include/link_elf.h b/libbsd/include/link_elf.h
index 7236b5d..679d8e1 100644
--- a/libbsd/include/link_elf.h
+++ b/libbsd/include/link_elf.h
@@ -10,26 +10,46 @@
#include <sys/types.h>
#include <machine/elf_machdep.h>
+#include <stdint.h>
-typedef struct link_map {
- caddr_t l_addr; /* Base Address of library */
-#ifdef __mips__
- caddr_t l_offs; /* Load Offset of library */
-#endif
- const char *l_name; /* Absolute Path to Library */
- void *l_ld; /* Pointer to .dynamic in memory */
- struct link_map *l_next; /* linked list of of mapped libs */
- struct link_map *l_prev;
-} Link_map;
+enum sections
+{
+ rap_text = 0,
+ rap_const = 1,
+ rap_ctor = 2,
+ rap_dtor = 3,
+ rap_data = 4,
+ rap_bss = 5,
+ rap_secs = 6
+};
+
+/**
+ * Object details.
+ */
+typedef struct
+{
+ char* name;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t rap_id;
+}section_detail;
+
+struct link_map {
+ char* name; /**< Name of the obj. */
+ uint32_t sec_num; /**< The count of section. */
+ section_detail* sec_detail; /**< The section details. */
+ uint32_t* sec_addr[rap_secs]; /**< The RAP section addr. */
+ struct link_map* l_next; /**< Linked list of mapped libs. */
+ struct link_map* l_prev;
+};
struct r_debug {
- int r_version; /* not used */
+ int r_version; /* not used */
struct link_map *r_map; /* list of loaded images */
- void (*r_brk)(void); /* pointer to break point */
enum {
- RT_CONSISTENT, /* things are stable */
- RT_ADD, /* adding a shared library */
- RT_DELETE /* removing a shared library */
+ RT_CONSISTENT, /* things are stable */
+ RT_ADD, /* adding a shared library */
+ RT_DELETE /* removing a shared library */
} r_state;
};
diff --git a/rtl-debugger.c b/rtl-debugger.c
index a240bfb..531b268 100644
--- a/rtl-debugger.c
+++ b/rtl-debugger.c
@@ -28,6 +28,8 @@
#include <link.h>
#include <rtl.h>
+#include <rtl-trace.h>
+#include "rtl-obj-fwd.h"
struct r_debug _rtld_debug;
@@ -38,3 +40,54 @@ _rtld_debug_state (void)
* Empty. GDB only needs to hit this location.
*/
}
+
+int
+_rtld_linkmap_add (rtems_rtl_obj_t* obj)
+{
+ struct link_map* l = (struct link_map*)obj->detail;
+ struct link_map* prev;
+ uint32_t obj_num = obj->obj_num;
+ int i;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: linkmap_add\n");
+
+ for (i = 0; i < obj_num; ++i)
+ {
+ l[i].sec_addr[rap_text] = obj->text_base;
+ l[i].sec_addr[rap_const] = obj->const_base;
+ l[i].sec_addr[rap_data] = obj->data_base;
+ l[i].sec_addr[rap_bss] = obj->bss_base;
+ }
+
+ if (_rtld_debug.r_map == NULL)
+ {
+ _rtld_debug.r_map = l;
+ return;
+ }
+
+ for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
+
+ l->l_prev = prev;
+ prev->l_next = l;
+}
+
+void
+_rtld_linkmap_delete (rtems_rtl_obj_t* obj)
+{
+ struct link_map* l = (struct link_map*)obj->detail;
+ /* link_maps are allocated together if not 1 */
+ struct link_map* e = l + obj->obj_num - 1;
+
+ while (e && e->l_next) e = e->l_next;
+
+ if (l->l_prev == NULL)
+ {
+ if ((_rtld_debug.r_map = e->l_next) != NULL)
+ e->l_next->l_prev = NULL;
+ return;
+ }
+ if ((l->l_prev->l_next = e->l_next) != NULL)
+ e->l_next->l_prev = l->l_prev;
+ return;
+}
diff --git a/rtl-obj.c b/rtl-obj.c
index ddf4a0b..f04925d 100644
--- a/rtl-obj.c
+++ b/rtl-obj.c
@@ -101,6 +101,10 @@ rtems_rtl_obj_free (rtems_rtl_obj_t* obj)
&obj->data_base, &obj->bss_base);
rtems_rtl_symbol_obj_erase (obj);
rtems_rtl_obj_free_names (obj);
+ if (obj->sec_num)
+ free (obj->sec_num);
+ if (obj->detail)
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*)obj->detail);
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
return true;
}
@@ -997,6 +1001,12 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
return false;
}
+ if (!_rtld_linkmap_add (obj)) /* For GDB */
+ {
+ close (fd);
+ return false;
+ }
+
rtems_rtl_obj_caches_flush ();
close (fd);
@@ -1007,6 +1017,7 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
bool
rtems_rtl_obj_unload (rtems_rtl_obj_t* obj)
{
+ _rtld_linkmap_delete(obj);
rtems_rtl_symbol_obj_erase (obj);
return rtems_rtl_obj_free (obj);
}
diff --git a/rtl-obj.h b/rtl-obj.h
index 5396a6c..2f7c403 100644
--- a/rtl-obj.h
+++ b/rtl-obj.h
@@ -163,6 +163,13 @@ struct rtems_rtl_obj_s
void* entry; /**< The entry point of the module. */
uint32_t checksum; /**< The checksum of the text sections. A
* zero means do not checksum. */
+ void* detail; /**< The file details. It contains the elf file
+ * detail, mainly including elf file name,
+ * section offset, section size, which
+ * elf this section belongs to.*/
+ uint32_t* sec_num; /**< The sec nums of each obj. */
+ uint32_t obj_num; /**< The count of elf files in an rtl obj. */
+ struct link_map* linkmap; /**< For GDB. */
};
/**
diff --git a/rtl-rap.c b/rtl-rap.c
index 808caf3..3633002 100644
--- a/rtl-rap.c
+++ b/rtl-rap.c
@@ -114,6 +114,8 @@ typedef struct rtems_rtl_rap_s
uint32_t strtab_size; /**< The string table size. */
uint32_t relocs_size; /**< The relocation table size. */
uint32_t symbols; /**< The number of symbols. */
+ uint32_t strtable_size;/**< The size of section names and obj names. */
+ char* strtable; /**< The detail string which resides in obj detail. */
} rtems_rtl_rap_t;
/**
@@ -423,6 +425,117 @@ rtems_rtl_rap_relocate (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
return true;
}
+/**
+ * The structure of obj->detail is
+ *
+ * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])|
+ * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num])
+ *
+ */
+static bool
+rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
+{
+ struct link_map* tmp1;
+ section_detail* tmp2;
+ uint32_t obj_detail_size;
+ uint32_t pos = 0;
+ uint32_t i,j;
+
+ obj_detail_size = sizeof (struct link_map) * obj->obj_num;
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ obj_detail_size += (obj->sec_num[i] * sizeof (section_detail));
+ }
+
+ obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ obj_detail_size + rap->strtable_size, true);
+
+ if (!obj->detail)
+ {
+ rap->strtable_size = 0;
+ rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
+ return false;
+ }
+
+ rap->strtable = obj->detail + obj_detail_size;
+
+ /* Read the obj names and section names */
+ if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtable,
+ rap->strtable_size))
+ {
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->detail);
+ return false;
+ }
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ tmp1 = (struct link_map*) (obj->detail) + i;
+ tmp1->name = rap->strtable + pos;
+ tmp1->sec_num = obj->sec_num[i];
+ pos += strlen (tmp1->name) + 1;
+
+ if (!i)
+ {
+ tmp1->l_next = NULL;
+ tmp1->l_prev = NULL;
+ }
+ else
+ {
+ (tmp1 - 1)->l_next = tmp1;
+ tmp1->l_prev = tmp1 - 1;
+ tmp1->l_next = NULL;
+ }
+ }
+
+ tmp2 =(section_detail*) ((struct link_map*) (obj->detail) + obj->obj_num);
+
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ printf ("File %u: %s\n", i, ((struct link_map*)obj->detail + i)->name);
+ printf ("Section: %u sections\n", obj->sec_num[i]);
+ }
+
+ ((struct link_map*)obj->detail + i)->sec_detail = tmp2;
+
+ for (j = 0; j < obj->sec_num[i]; ++j)
+ {
+ uint32_t name;
+ uint32_t rap_id;
+ uint32_t offset;
+ uint32_t size;
+
+ if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) ||
+ !rtems_rtl_rap_read_uint32 (rap->decomp, &size))
+ {
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->detail);
+ return false;
+ }
+
+ rap_id = offset >> 28;
+ offset = offset & 0xfffffff;
+
+ tmp2->name = rap->strtable + name;
+ tmp2->offset = offset;
+ tmp2->rap_id = rap_id;
+ tmp2->size = size;
+ pos += strlen (tmp2->name) + 1;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ {
+ printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n",
+ tmp2->name, tmp2->offset, tmp2->rap_id, tmp2->size);
+ }
+
+ tmp2 += 1;
+ }
+ }
+ return true;
+}
+
static bool
rtems_rtl_rap_load_symbols (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
{
@@ -746,6 +859,33 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
rap.strtab_size, rap.relocs_size);
/*
+ * Load the details
+ */
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num))
+ return false;
+
+ if (obj->obj_num > 0)
+ {
+ obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num);
+
+ uint32_t i;
+ for (i = 0; i < obj->obj_num; ++i)
+ {
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i])))
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: rap: details: obj_num=%lu\n", obj->obj_num);
+
+ if (!rtems_rtl_rap_load_details (&rap, obj))
+ return false;
+ }
+
+ /*
* uint32_t: text_size
* uint32_t: text_alignment
* uint32_t: const_size
diff --git a/rtl-trace.c b/rtl-trace.c
index bc3780d..cb9f35f 100644
--- a/rtl-trace.c
+++ b/rtl-trace.c
@@ -66,7 +66,8 @@ rtems_rtl_trace_shell_command (int argc, char *argv[])
"global-sym",
"load-sect",
"allocator",
- "unresolved"
+ "unresolved",
+ "detail"
};
rtems_rtl_trace_mask set_value = 0;
diff --git a/rtl-trace.h b/rtl-trace.h
index fea8122..1a5ee97 100644
--- a/rtl-trace.h
+++ b/rtl-trace.h
@@ -46,6 +46,7 @@ typedef uint32_t rtems_rtl_trace_mask;
#define RTEMS_RTL_TRACE_LOAD_SECT (1UL << 6)
#define RTEMS_RTL_TRACE_ALLOCATOR (1UL << 7)
#define RTEMS_RTL_TRACE_UNRESOLVED (1UL << 8)
+#define RTEMS_RTL_TRACE_DETAIL (1UL << 9)
/**
* Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to