From 4a6cfe318094cc8b20e6e3003f417f8ab3563bb1 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 9 May 2002 08:34:43 +0000 Subject: Another mips patch from Steven J. Hill: Uh, this patch fixes a few bugs that I overlooked. Shoot, even BusyBox wouldn't work until these are applied. Erik, plop this into CVS please. Thanks. --- ldso/ldso/dl-elf.c | 37 +++++++++--------------- ldso/ldso/dl-hash.c | 18 +++++++++++- ldso/ldso/hash.c | 18 +++++++++++- ldso/ldso/ldso.c | 71 ++++++++++++++++++++++++++++++---------------- ldso/ldso/mips/dl-sysdep.h | 8 +++--- ldso/ldso/mips/ld_sysdep.h | 8 +++--- ldso/ldso/mips/resolve.S | 14 +++++---- ldso/ldso/readelflib1.c | 37 +++++++++--------------- 8 files changed, 123 insertions(+), 88 deletions(-) diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 7dbbe6f4b..ebb0aec56 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -315,11 +315,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, 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); @@ -529,22 +524,21 @@ 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++) + { + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + + while(dpnt->d_tag) { + dpnt++; + i++; + } + dynamic_size = i * sizeof(Elf32_Dyn); + } #endif + + for (i = 0; i < dynamic_size; i++) { if (dpnt->d_tag > DT_JMPREL) { dpnt++; @@ -601,11 +595,6 @@ 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); }; diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index c6c77e748..b063d0b79 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -125,6 +125,21 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname, tpnt->loadaddr = loadaddr; for (i = 0; i < 24; i++) tpnt->dynamic_info[i] = dynamic_info[i]; +#ifdef __mips__ + { + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + + while(dpnt->d_tag) { + if (dpnt->d_tag == DT_MIPS_GOTSYM) + tpnt->mips_gotsym = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) + tpnt->mips_local_gotno = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_SYMTABNO) + tpnt->mips_symtabno = dpnt->d_un.d_val; + dpnt++; + } + } +#endif return tpnt; } @@ -235,7 +250,8 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC || ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE || ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) && - symtab[si].st_value != 0) { + symtab[si].st_value != 0 && + symtab[si].st_shndx != 0) { /* Here we make sure that we find a module where the symbol is * actually defined. diff --git a/ldso/ldso/hash.c b/ldso/ldso/hash.c index c6c77e748..b063d0b79 100644 --- a/ldso/ldso/hash.c +++ b/ldso/ldso/hash.c @@ -125,6 +125,21 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname, tpnt->loadaddr = loadaddr; for (i = 0; i < 24; i++) tpnt->dynamic_info[i] = dynamic_info[i]; +#ifdef __mips__ + { + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + + while(dpnt->d_tag) { + if (dpnt->d_tag == DT_MIPS_GOTSYM) + tpnt->mips_gotsym = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) + tpnt->mips_local_gotno = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_MIPS_SYMTABNO) + tpnt->mips_symtabno = dpnt->d_un.d_val; + dpnt++; + } + } +#endif return tpnt; } @@ -235,7 +250,8 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC || ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE || ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) && - symtab[si].st_value != 0) { + symtab[si].st_value != 0 && + symtab[si].st_shndx != 0) { /* Here we make sure that we find a module where the symbol is * actually defined. diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index f9029006c..d2eee0555 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -368,12 +368,6 @@ DL_BOOT(unsigned long args) /* OK, that was easy. Next scan the DYNAMIC section of the image. We are only doing ourself right now - we will have to do the rest later */ while (dpnt->d_tag) { - if (dpnt->d_tag < 24) { - tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; - if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT) { - tpnt->dynamic_info[DT_TEXTREL] = 1; - } - } #if defined(__mips__) if (dpnt->d_tag == DT_MIPS_GOTSYM) tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val; @@ -382,6 +376,12 @@ DL_BOOT(unsigned long args) if (dpnt->d_tag == DT_MIPS_SYMTABNO) tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val; #endif + if (dpnt->d_tag < 24) { + tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT) { + tpnt->dynamic_info[DT_TEXTREL] = 1; + } + } dpnt++; } @@ -473,9 +473,10 @@ DL_BOOT(unsigned long args) #endif - /* For MIPS, we have to do special stuff to the GOT before we do - any relocations. */ #if defined(__mips__) + /* + * For MIPS we have to do stuff to the GOT before we do relocations. + */ PERFORM_BOOTSTRAP_GOT(got); #endif @@ -612,11 +613,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a struct elf_resolve *tpnt1; unsigned long brk_addr, *lpnt; int (*_dl_atexit) (void *); -#ifdef __mips__ - unsigned long mips_gotsym = 0; - unsigned long mips_local_gotno = 0; - unsigned long mips_symtabno = 0; -#endif /* Now we have done the mandatory linking of some things. We are now @@ -649,7 +645,20 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a for (i = 0; i < epnt->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_DYNAMIC) { tpnt->dynamic_addr = ppnt->p_vaddr + load_addr; +#if defined(__mips__) + { + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) tpnt->dynamic_addr; + + while(dpnt->d_tag) { + dpnt++; + i++; + } + tpnt->dynamic_size = i * sizeof(Elf32_Dyn); + } +#else tpnt->dynamic_size = ppnt->p_filesz; +#endif } } } @@ -674,31 +683,38 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a continue; #endif /* OK, we have what we need - slip this one into the list. */ -#ifdef __mips__ - mips_gotsym = app_tpnt->mips_gotsym; - mips_local_gotno = app_tpnt->mips_local_gotno; - mips_symtabno = app_tpnt->mips_symtabno; -#endif +#if defined(__mips__) + { + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) tpnt->dynamic_addr; + + while(dpnt->d_tag) { + dpnt++; + i++; + } + app_tpnt = _dl_add_elf_hash_table("", 0, + app_tpnt->dynamic_info, ppnt->p_vaddr, + (i * sizeof(Elf32_Dyn))); + } +#else app_tpnt = _dl_add_elf_hash_table("", 0, app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz); +#endif _dl_loaded_modules->libtype = elf_executable; _dl_loaded_modules->ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr; _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; -#ifdef __mips__ - _dl_loaded_modules->mips_gotsym = mips_gotsym; - _dl_loaded_modules->mips_local_gotno = mips_local_gotno; - _dl_loaded_modules->mips_symtabno = mips_symtabno; -#endif _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(*rpnt)); rpnt->dyn = _dl_loaded_modules; app_tpnt->usage_count++; app_tpnt->symbol_scope = _dl_symbol_tables; lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]); +#ifndef __mips__ #ifdef ALLOW_ZERO_PLTGOT if (lpnt) #endif INIT_GOT(lpnt, _dl_loaded_modules); +#endif } /* OK, fill this in - we did not have this before */ @@ -1063,8 +1079,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a up each symbol individually. */ - _dl_brkp = - (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, 0); + _dl_brkp = (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, 0); + if (_dl_brkp) { *_dl_brkp = brk_addr; } @@ -1075,6 +1091,11 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a *_dl_envp = (unsigned long) envp; } +#ifdef __mips__ + lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]); + INIT_GOT(lpnt, _dl_loaded_modules); +#endif + #ifdef DO_MPROTECT_HACKS { int i; diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h index f54e812b7..9d48d8f73 100644 --- a/ldso/ldso/mips/dl-sysdep.h +++ b/ldso/ldso/mips/dl-sysdep.h @@ -20,7 +20,7 @@ /* - * Initialization sequence for the application GOT. + * Initialization sequence for the application or library GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ do { \ @@ -56,12 +56,12 @@ do { \ (unsigned long) MODULE->loadaddr; \ else { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ } \ else if (sym->st_shndx == SHN_COMMON) { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ *GOT_BASE != sym->st_value) \ @@ -72,7 +72,7 @@ do { \ } \ else { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ \ ++GOT_BASE; \ diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h index f54e812b7..9d48d8f73 100644 --- a/ldso/ldso/mips/ld_sysdep.h +++ b/ldso/ldso/mips/ld_sysdep.h @@ -20,7 +20,7 @@ /* - * Initialization sequence for the application GOT. + * Initialization sequence for the application or library GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ do { \ @@ -56,12 +56,12 @@ do { \ (unsigned long) MODULE->loadaddr; \ else { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ } \ else if (sym->st_shndx == SHN_COMMON) { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ *GOT_BASE != sym->st_value) \ @@ -72,7 +72,7 @@ do { \ } \ else { \ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 0); \ + sym->st_name, MODULE->symbol_scope, NULL, 1); \ } \ \ ++GOT_BASE; \ diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S index b6dda82d7..f1d7cff76 100644 --- a/ldso/ldso/mips/resolve.S +++ b/ldso/ldso/mips/resolve.S @@ -23,18 +23,22 @@ _dl_linux_resolve: addu $25, 8 # t9 ($25) now points at .cpload instruction .cpload $25 # Compute GP .set reorder - subu $29, 32 - .cprestore 28 + subu $29, 40 + .cprestore 32 + sw $15, 36($29) sw $4, 16($29) sw $5, 20($29) - sw $15, 24($29) + sw $6, 24($29) + sw $7, 28($29) move $4, $24 move $5, $3 jal _dl_linux_resolver - lw $31, 24($29) + lw $31, 36($29) lw $4, 16($29) lw $5, 20($29) - addu $29, 32 + lw $6, 24($29) + lw $7, 28($29) + addu $29, 40 move $25, $2 jr $25 .size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index 7dbbe6f4b..ebb0aec56 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -315,11 +315,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, 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); @@ -529,22 +524,21 @@ 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++) + { + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + + while(dpnt->d_tag) { + dpnt++; + i++; + } + dynamic_size = i * sizeof(Elf32_Dyn); + } #endif + + for (i = 0; i < dynamic_size; i++) { if (dpnt->d_tag > DT_JMPREL) { dpnt++; @@ -601,11 +595,6 @@ 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