diff options
author | dfr <dfr@FreeBSD.org> | 1998-04-30 07:48:02 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-04-30 07:48:02 +0000 |
commit | ff6b56dce1f6bb2a9a2abb85e17615af33850b1e (patch) | |
tree | 9e2c95c6e6c4a487c0a2e99bce1cef5f7b2553e6 /libexec/rtld-elf | |
parent | e2f2fa5616fb3a8268843da4ed303d7397e839ca (diff) | |
download | FreeBSD-src-ff6b56dce1f6bb2a9a2abb85e17615af33850b1e.zip FreeBSD-src-ff6b56dce1f6bb2a9a2abb85e17615af33850b1e.tar.gz |
Add GDB support. The method and some of the code came from NetBSD's elf
runtime linker.
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r-- | libexec/rtld-elf/Makefile | 4 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.c | 115 | ||||
-rw-r--r-- | libexec/rtld-elf/rtld.h | 5 |
3 files changed, 102 insertions, 22 deletions
diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index cc6dfbe..e7c0eb8 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -1,11 +1,11 @@ # -# $Id: Makefile,v 1.5 1998/03/05 21:05:47 jdp Exp $ +# $Id: Makefile,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $ # PROG= ld-elf.so.1 SRCS= rtld_start.S rtld.c map_object.c malloc.c xmalloc.c debug.c NOMAN= true -CFLAGS+= -elf -fpic +CFLAGS+= -elf -fpic -DFREEBSD_ELF CFLAGS+= -Wall LDFLAGS+= -elf -nostdlib -Wl,-Bshareable,-Bsymbolic LDADD+= -lc_pic diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 73194e0..50a392f 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.c,v 1.18 1998/03/06 22:14:54 jdp Exp $ + * $Id: rtld.c,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $ */ /* @@ -90,6 +90,9 @@ static char *search_library_path(const char *, const char *); static const Elf32_Sym *symlook_obj(const char *, unsigned long, const Obj_Entry *, bool); static void unref_object_dag(Obj_Entry *); +void r_debug_state(void); +static void linkmap_add(Obj_Entry *); +static void linkmap_delete(Obj_Entry *); void xprintf(const char *, ...); @@ -116,6 +119,7 @@ extern void _rtld_bind_start(void); * Data declarations. */ static char *error_message; /* Message for dlerror(), or NULL */ +struct r_debug r_debug; /* for GDB; */ static bool trust; /* False for setuid and setgid programs */ static char *ld_bind_now; /* Environment variable for immediate binding */ static char *ld_debug; /* Environment variable for debugging */ @@ -125,6 +129,8 @@ static Obj_Entry **obj_tail; /* Link field of last object in list */ static Obj_Entry *obj_main; /* The main program shared object */ static Obj_Entry obj_rtld; /* The dynamic linker shared object */ +#define GDB_STATE(s) r_debug.r_state = s; r_debug_state(); + /* * These are the functions the dynamic linker exports to application * programs. They are the only symbols the dynamic linker is willing @@ -248,6 +254,9 @@ _rtld(Elf32_Word *sp, func_ptr_type *exit_proc) obj_main->mainprog = true; digest_dynamic(obj_main); + linkmap_add(obj_main); + linkmap_add(&obj_rtld); + /* Link the main program into the list of objects. */ *obj_tail = obj_main; obj_tail = &obj_main->next; @@ -271,6 +280,8 @@ _rtld(Elf32_Word *sp, func_ptr_type *exit_proc) dbg("transferring control to program entry point = %p", obj_main->entry); + r_debug_state(); /* say hello to gdb! */ + /* Return the exit procedure and the program entry point. */ *exit_proc = (func_ptr_type) rtld_exit; return (func_ptr_type) obj_main->entry; @@ -479,6 +490,8 @@ digest_dynamic(Obj_Entry *obj) case DT_DEBUG: /* XXX - not implemented yet */ + dbg("Filling in DT_DEBUG entry"); + ((Elf32_Dyn*)dynp)->d_un.d_ptr = (Elf32_Addr) &r_debug; break; } } @@ -783,6 +796,9 @@ init_rtld(caddr_t mapbase) /* Make the object list empty again. */ obj_list = NULL; obj_tail = &obj_list; + + r_debug.r_brk = r_debug_state; + r_debug.r_state = RT_CONSISTENT; } static bool @@ -863,6 +879,7 @@ load_object(char *path) *obj_tail = obj; obj_tail = &obj->next; + linkmap_add(obj); /* for GDB */ dbg(" %p .. %p: %s", obj->mapbase, obj->mapbase + obj->mapsize - 1, obj->path); @@ -1056,8 +1073,10 @@ relocate_objects(Obj_Entry *first, bool bind_now) obj->version = RTLD_VERSION; /* Set the special GOT entries. */ - obj->got[1] = (Elf32_Addr) obj; - obj->got[2] = (Elf32_Addr) &_rtld_bind_start; + if (obj->got) { + obj->got[1] = (Elf32_Addr) obj; + obj->got[2] = (Elf32_Addr) &_rtld_bind_start; + } } return 0; @@ -1118,6 +1137,8 @@ dlclose(void *handle) if (root == NULL) return -1; + GDB_STATE(RT_DELETE); + root->dl_refcount--; unref_object_dag(root); if (root->refcount == 0) { /* We are finished with some objects. */ @@ -1140,6 +1161,7 @@ dlclose(void *handle) obj->needed = needed->next; free(needed); } + linkmap_delete(obj); *linkp = obj->next; free(obj); } else @@ -1147,6 +1169,8 @@ dlclose(void *handle) } } + GDB_STATE(RT_CONSISTENT); + return 0; } @@ -1162,30 +1186,37 @@ void * dlopen(const char *name, int mode) { Obj_Entry **old_obj_tail = obj_tail; - Obj_Entry *obj; + Obj_Entry *obj = NULL; + + GDB_STATE(RT_ADD); if (name == NULL) obj = obj_main; else { char *path = find_library(name, NULL); - if (path == NULL) - return NULL; - obj = load_object(path); - if (obj == NULL) - return NULL; + if (path != NULL) + obj = load_object(path); } - obj->dl_refcount++; - if (*old_obj_tail != NULL) { /* We loaded something new. */ - assert(*old_obj_tail == obj); - - /* XXX - Clean up properly after an error. */ - if (load_needed_objects(obj) == -1) - return NULL; - if (relocate_objects(obj, mode == RTLD_NOW) == -1) - return NULL; - call_init_functions(obj); + if (obj) { + obj->dl_refcount++; + if (*old_obj_tail != NULL) { /* We loaded something new. */ + assert(*old_obj_tail == obj); + + /* XXX - Clean up properly after an error. */ + if (load_needed_objects(obj) == -1) { + obj->dl_refcount--; + obj = NULL; + } else if (relocate_objects(obj, mode == RTLD_NOW) == -1) { + obj->dl_refcount--; + obj = NULL; + } else + call_init_functions(obj); + } } + + GDB_STATE(RT_CONSISTENT); + return obj; } @@ -1227,6 +1258,7 @@ dlsym(void *handle, const char *name) return NULL; } + /* * Search the symbol table of a single shared object for a symbol of * the given name. Returns a pointer to the symbol, or NULL if no @@ -1289,3 +1321,48 @@ xprintf(const char *fmt, ...) (void)write(1, buf, strlen(buf)); va_end(ap); } + +void +r_debug_state(void) +{ +} + +static void +linkmap_add(Obj_Entry *obj) +{ + struct link_map *l = &obj->linkmap; + struct link_map *prev; + + obj->linkmap.l_name = obj->path; + obj->linkmap.l_addr = obj->mapbase; + obj->linkmap.l_ld = obj->dynamic; +#ifdef __mips__ + /* GDB needs load offset on MIPS to use the symbols */ + obj->linkmap.l_offs = obj->relocbase; +#endif + + if (r_debug.r_map == NULL) { + r_debug.r_map = l; + return; + } + + for (prev = r_debug.r_map; prev->l_next != NULL; prev = prev->l_next) + ; + l->l_prev = prev; + prev->l_next = l; + l->l_next = NULL; +} + +void linkmap_delete(Obj_Entry *obj) +{ + struct link_map *l = &obj->linkmap; + + if (l->l_prev == NULL) { + if ((r_debug.r_map = l->l_next) != NULL) + l->l_next->l_prev = NULL; + return; + } + + if ((l->l_prev->l_next = l->l_next) != NULL) + l->l_next->l_prev = l->l_prev; +} diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index cbd7d8b..c5343a8 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: rtld.h,v 1.3 1998/03/06 14:00:09 jdp Exp $ + * $Id: rtld.h,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $ */ #ifndef RTLD_H /* { */ @@ -30,6 +30,7 @@ #include <sys/types.h> +#include <link.h> #include <elf.h> #include <stddef.h> @@ -108,6 +109,8 @@ typedef struct Struct_Obj_Entry { bool rtld; /* True if this is the dynamic linker */ bool textrel; /* True if there are relocations to text seg */ bool symbolic; /* True if generated with "-Bsymbolic" */ + + struct link_map linkmap; /* for GDB */ } Obj_Entry; #define RTLD_MAGIC 0xd550b87a |