diff options
author | jake <jake@FreeBSD.org> | 2002-04-02 02:19:02 +0000 |
---|---|---|
committer | jake <jake@FreeBSD.org> | 2002-04-02 02:19:02 +0000 |
commit | 6f01a2296f0fcd6e8dd625aa2b6ee0d2da57686a (patch) | |
tree | 6e1afa0654591fac90c27fc61b23707eaca9ee52 /libexec/rtld-elf | |
parent | f6a3790f10b11d31fb0e40c5640411147785a19f (diff) | |
download | FreeBSD-src-6f01a2296f0fcd6e8dd625aa2b6ee0d2da57686a.zip FreeBSD-src-6f01a2296f0fcd6e8dd625aa2b6ee0d2da57686a.tar.gz |
Minor changes to make this work on sparc64.
Approved by: jdp
Tested on: alpha, i386, sparc64
Diffstat (limited to 'libexec/rtld-elf')
-rw-r--r-- | libexec/rtld-elf/rtld.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 619791e..c4cc5e8 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -73,7 +73,7 @@ typedef struct Struct_DoneList { */ static const char *basename(const char *); static void die(void); -static void digest_dynamic(Obj_Entry *); +static void digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); static Obj_Entry *dlcheck(void *); static bool donelist_check(DoneList *, const Obj_Entry *); @@ -104,7 +104,7 @@ static void objlist_push_head(Objlist *, Obj_Entry *); static void objlist_push_tail(Objlist *, Obj_Entry *); static void objlist_remove(Objlist *, Obj_Entry *); static void objlist_remove_unref(Objlist *); -static int relocate_objects(Obj_Entry *, bool); +static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); static void rtld_exit(void); static char *search_library_path(const char *, const char *); static const void **get_program_var_addr(const char *name); @@ -342,7 +342,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) obj_rtld.path = xstrdup(obj_main->interp); } - digest_dynamic(obj_main); + digest_dynamic(obj_main, 0); linkmap_add(obj_main); linkmap_add(&obj_rtld); @@ -378,7 +378,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) } if (relocate_objects(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0') == -1) + ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) die(); dbg("doing copy relocations"); @@ -513,7 +513,7 @@ die(void) * information in its Obj_Entry structure. */ static void -digest_dynamic(Obj_Entry *obj) +digest_dynamic(Obj_Entry *obj, int early) { const Elf_Dyn *dynp; Needed_Entry **needed_tail = &obj->needed; @@ -635,13 +635,16 @@ digest_dynamic(Obj_Entry *obj) case DT_DEBUG: /* XXX - not implemented yet */ - dbg("Filling in DT_DEBUG entry"); + if (!early) + dbg("Filling in DT_DEBUG entry"); ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; break; default: - dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, - (long)dynp->d_tag); + if (!early) { + dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, + (long)dynp->d_tag); + } break; } } @@ -854,7 +857,17 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj, hash = elf_hash(name); defobj = NULL; - def = symlook_default(name, hash, refobj, &defobj, in_plt); + /* Handle STT_SECTION specially. */ + if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { + if (ELF_ST_BIND(ref->st_info) != STB_LOCAL || + ref->st_shndx != symnum) { + _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, + symnum); + } + def = ref; + defobj = refobj; + } else + def = symlook_default(name, hash, refobj, &defobj, in_plt); /* * If we found no definition and the reference is weak, treat the @@ -949,43 +962,42 @@ init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp) static void init_rtld(caddr_t mapbase) { + Obj_Entry objtmp; /* Temporary rtld object */ + /* * Conjure up an Obj_Entry structure for the dynamic linker. * - * The "path" member is supposed to be dynamically-allocated, but we - * aren't yet initialized sufficiently to do that. Below we will - * replace the static version with a dynamically-allocated copy. + * The "path" member can't be initialized yet because string constatns + * cannot yet be acessed. Below we will set it correctly. */ - obj_rtld.path = PATH_RTLD; - obj_rtld.rtld = true; - obj_rtld.mapbase = mapbase; + objtmp.path = NULL; + objtmp.rtld = true; + objtmp.mapbase = mapbase; #ifdef PIC - obj_rtld.relocbase = mapbase; + objtmp.relocbase = mapbase; #endif if (&_DYNAMIC != 0) { - obj_rtld.dynamic = rtld_dynamic(&obj_rtld); - digest_dynamic(&obj_rtld); - assert(obj_rtld.needed == NULL); - assert(!obj_rtld.textrel); + objtmp.dynamic = rtld_dynamic(&objtmp); + digest_dynamic(&objtmp, 1); + assert(objtmp.needed == NULL); + assert(!objtmp.textrel); /* * Temporarily put the dynamic linker entry into the object list, so * that symbols can be found. */ - obj_list = &obj_rtld; - obj_tail = &obj_rtld.next; - obj_count = 1; - relocate_objects(&obj_rtld, true); + relocate_objects(&objtmp, true, &objtmp); } - /* Make the object list empty again. */ - obj_list = NULL; + /* Initialize the object list. */ obj_tail = &obj_list; - obj_count = 0; + + /* Now that non-local variables can be accesses, copy out obj_rtld. */ + memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); /* Replace the path with a dynamically allocated copy. */ - obj_rtld.path = xstrdup(obj_rtld.path); + obj_rtld.path = xstrdup(PATH_RTLD); r_debug.r_brk = r_debug_state; r_debug.r_state = RT_CONSISTENT; @@ -1174,7 +1186,7 @@ load_object(char *path) } obj->path = path; - digest_dynamic(obj); + digest_dynamic(obj, 0); *obj_tail = obj; obj_tail = &obj->next; @@ -1370,12 +1382,12 @@ objlist_remove_unref(Objlist *list) * or -1 on failure. */ static int -relocate_objects(Obj_Entry *first, bool bind_now) +relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) { Obj_Entry *obj; for (obj = first; obj != NULL; obj = obj->next) { - if (obj != &obj_rtld) + if (obj != rtldobj) dbg("relocating \"%s\"", obj->path); if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || obj->symtab == NULL || obj->strtab == NULL) { @@ -1395,7 +1407,7 @@ relocate_objects(Obj_Entry *first, bool bind_now) } /* Process the non-PLT relocations. */ - if (reloc_non_plt(obj, &obj_rtld)) + if (reloc_non_plt(obj, rtldobj)) return -1; if (obj->textrel) { /* Re-protected the text segment. */ @@ -1595,7 +1607,8 @@ dlopen(const char *name, int mode) } if (result == -1 || - (init_dag(obj), relocate_objects(obj, mode == RTLD_NOW)) == -1) { + (init_dag(obj), relocate_objects(obj, mode == RTLD_NOW, + &obj_rtld)) == -1) { obj->dl_refcount--; unref_dag(obj); if (obj->refcount == 0) |