From 4a5a81ac165c040935a8807a580db49d381dc443 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 2 May 2002 13:36:53 +0000 Subject: Patch from Steven J. Hill : I am very pleased to announce that the MIPS dynamic linker/loader for uClibc is now working. It works on big and little endian platforms. A few minor changes were needed to avoid breaking ldd, and since this makes some non-trivial changes, I have tested on x86, arm, and powerpc to be sure thoese arches didn't get broken. Excellent work Steven! --- ldso/ldso/dl-elf.c | 85 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 19 deletions(-) (limited to 'ldso/ldso/dl-elf.c') diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 913ac8778..b758df2d6 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -108,14 +108,14 @@ int _dl_unmap_cache(void) /* This function's behavior must exactly match that * in uClibc/ldso/util/ldd.c */ static struct elf_resolve * -search_for_named_library(char *name, int secure, const char *path_list) +search_for_named_library(char *name, int secure, const char *path_list, + struct dyn_elf **rpnt) { int i, count = 1; char *path, *path_n; char mylibname[2050]; struct elf_resolve *tpnt1; - /* We need a writable copy of this string */ path = _dl_strdup(path_list); if (!path) { @@ -140,8 +140,11 @@ search_for_named_library(char *name, int secure, const char *path_list) _dl_strcpy(mylibname, path_n); _dl_strcat(mylibname, "/"); _dl_strcat(mylibname, name); - if ((tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0)) != NULL) - return tpnt1; + if ((tpnt1 = _dl_load_elf_shared_library(secure, rpnt, + mylibname, 0)) != NULL) + { + return tpnt1; + } path_n += (_dl_strlen(path_n) + 1); } return NULL; @@ -156,7 +159,7 @@ unsigned long _dl_error_number; unsigned long _dl_internal_error_number; extern char *_dl_ldsopath; -struct elf_resolve *_dl_load_shared_library(int secure, +struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname) { char *pnt; @@ -185,7 +188,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, /usr/i486-sysv4/lib for /usr/lib in library names. */ if (libname != full_libname) { - tpnt1 = _dl_load_elf_shared_library(secure, full_libname, 0); + tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname, 0); if (tpnt1) return tpnt1; goto goof; @@ -204,7 +207,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, #ifdef DL_DEBUG _dl_dprintf(2, "searching RPATH: '%s'\n", pnt); #endif - if ((tpnt1 = search_for_named_library(libname, secure, pnt)) != NULL) + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) { return tpnt1; } @@ -217,7 +220,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, #ifdef DL_DEBUG _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path); #endif - if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path)) != NULL) + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) { return tpnt1; } @@ -240,7 +243,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, libent[i].flags == LIB_ELF_LIBC5) && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 && (tpnt1 = _dl_load_elf_shared_library(secure, - strs + libent[i].liboffset, 0))) + rpnt, strs + libent[i].liboffset, 0))) return tpnt1; } } @@ -251,7 +254,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, #ifdef DL_DEBUG _dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath); #endif - if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath)) != NULL) + if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) { return tpnt1; } @@ -268,7 +271,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, UCLIBC_DEVEL_PREFIX "/lib:" UCLIBC_BUILD_DIR "/lib:" "/usr/lib:" - "/lib") + "/lib", rpnt) ) != NULL) { return tpnt1; @@ -286,16 +289,15 @@ goof: return NULL; } + /* * Read one ELF library into memory, mmap it into the correct locations and * add the symbol info to the symbol chain. Perform any relocations that * are required. */ -//extern _elf_rtbndr(void); - -struct elf_resolve *_dl_load_elf_shared_library(int secure, - char *libname, int flag) +struct elf_resolve *_dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname, int flag) { elfhdr *epnt; unsigned long dynamic_addr = 0; @@ -311,14 +313,27 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, unsigned long *lpnt; unsigned long libaddr; unsigned long minvma = 0xffffffff, maxvma = 0; - int i; int infile; +#if defined(__mips__) + unsigned long mips_gotsym = 0; + unsigned long mips_local_gotno = 0; + unsigned long mips_symtabno = 0; +#endif /* If this file is already loaded, skip this step */ tpnt = _dl_check_hashed_files(libname); - if (tpnt) + if (tpnt) { + (*rpnt)->next = (struct dyn_elf *) + _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next))); + *rpnt = (*rpnt)->next; + tpnt->usage_count++; + tpnt->symbol_scope = _dl_symbol_tables; + tpnt->libtype = elf_lib; + (*rpnt)->dyn = tpnt; return tpnt; + } /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), we don't load the library if it isn't setuid. */ @@ -514,7 +529,22 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, dynamic_size = dynamic_size / sizeof(Elf32_Dyn); _dl_memset(dynamic_info, 0, sizeof(dynamic_info)); +#if defined(__mips__) + /* + * The program header file size for the dynamic section is + * calculated differently for MIPS. We look for a null tag + * value instead. + */ + while(dpnt->d_tag) { + if (dpnt->d_tag == DT_MIPS_GOTSYM) + mips_gotsym = (unsigned long) dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) + mips_local_gotno = (unsigned long) dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_SYMTABNO) + mips_symtabno = (unsigned long) dpnt->d_un.d_val; +#else for (i = 0; i < dynamic_size; i++) { +#endif if (dpnt->d_tag > DT_JMPREL) { dpnt++; continue; @@ -526,8 +556,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, }; /* If the TEXTREL is set, this means that we need to make the pages - writable before we perform relocations. Do this now. They get set back - again later. */ + writable before we perform relocations. Do this now. They get set + back again later. */ if (dynamic_info[DT_TEXTREL]) { ppnt = (elf_phdr *) & header[epnt->e_phoff]; @@ -547,6 +577,18 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, tpnt->ppnt = (elf_phdr *) (tpnt->loadaddr + epnt->e_phoff); tpnt->n_phent = epnt->e_phnum; + /* + * Add this object into the symbol chain + */ + (*rpnt)->next = (struct dyn_elf *) + _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next))); + *rpnt = (*rpnt)->next; + tpnt->usage_count++; + tpnt->symbol_scope = _dl_symbol_tables; + tpnt->libtype = elf_lib; + (*rpnt)->dyn = tpnt; + /* * OK, the next thing we need to do is to insert the dynamic linker into * the proper entry in the GOT so that the PLT symbols can be properly @@ -558,6 +600,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, if (lpnt) { lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] + ((int) libaddr)); +#if defined(__mips__) + tpnt->mips_gotsym = mips_gotsym; + tpnt->mips_local_gotno = mips_local_gotno; + tpnt->mips_symtabno = mips_symtabno; +#endif INIT_GOT(lpnt, tpnt); }; -- cgit v1.2.3