summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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