diff options
-rw-r--r-- | libbsd/include/link_elf.h | 50 | ||||
-rw-r--r-- | rtl-debugger.c | 53 | ||||
-rw-r--r-- | rtl-obj.c | 11 | ||||
-rw-r--r-- | rtl-obj.h | 7 | ||||
-rw-r--r-- | rtl-rap.c | 140 | ||||
-rw-r--r-- | rtl-trace.c | 3 | ||||
-rw-r--r-- | rtl-trace.h | 1 |
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; +} @@ -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); } @@ -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. */ }; /** @@ -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 |