From 1e811cd2c026257eb9adc27f0978698cdc226c26 Mon Sep 17 00:00:00 2001 From: "\"Steven J. Hill\"" Date: Mon, 20 May 2002 18:30:17 +0000 Subject: Fixed MIPS dynamic linker by removing link order dependency bug. --- ldso/ldso/dl-elf.c | 14 +++++------ ldso/ldso/ldso.c | 15 ++++++------ ldso/ldso/mips/boot1_arch.h | 5 +++- ldso/ldso/mips/dl-startup.h | 5 +++- ldso/ldso/mips/dl-sysdep.h | 41 +------------------------------ ldso/ldso/mips/elfinterp.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ ldso/ldso/mips/ld_sysdep.h | 41 +------------------------------ ldso/ldso/readelflib1.c | 14 +++++------ 8 files changed, 91 insertions(+), 103 deletions(-) (limited to 'ldso/ldso') diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index ebb0aec56..1bbb79364 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -527,14 +527,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, #if defined(__mips__) { - int i = 1; - Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; - while(dpnt->d_tag) { - dpnt++; - i++; - } - dynamic_size = i * sizeof(Elf32_Dyn); + while(dpnt->d_tag) { + dpnt++; + i++; + } + dynamic_size = i; } #endif diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index d2eee0555..5c3f38d30 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -709,12 +709,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a 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 */ @@ -1046,6 +1044,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a } #endif +#ifdef __mips__ + /* + * Relocation of the GOT entries for MIPS have to be done + * after all the libraries have been loaded. + */ + _dl_perform_mips_global_got_relocations(_dl_loaded_modules); +#endif + #ifdef DL_DEBUG _dl_dprintf(2, "Beginning relocation fixups\n"); #endif @@ -1091,11 +1097,6 @@ 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/boot1_arch.h b/ldso/ldso/mips/boot1_arch.h index 05aaf9ebb..6dda467e8 100644 --- a/ldso/ldso/mips/boot1_arch.h +++ b/ldso/ldso/mips/boot1_arch.h @@ -16,8 +16,11 @@ _dl_boot: sw $4, -0x7ff0($28) move $4, $29 la $8, coff - bltzal $8, coff + .set noreorder + bltzal $0, coff + nop coff: subu $8, $31, $8 + .set reorder la $25, _dl_boot2 addu $25, $8 jalr $25 diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h index 05aaf9ebb..6dda467e8 100644 --- a/ldso/ldso/mips/dl-startup.h +++ b/ldso/ldso/mips/dl-startup.h @@ -16,8 +16,11 @@ _dl_boot: sw $4, -0x7ff0($28) move $4, $29 la $8, coff - bltzal $8, coff + .set noreorder + bltzal $0, coff + nop coff: subu $8, $31, $8 + .set reorder la $25, _dl_boot2 addu $25, $8 jalr $25 diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h index 9d48d8f73..a669bba67 100644 --- a/ldso/ldso/mips/dl-sysdep.h +++ b/ldso/ldso/mips/dl-sysdep.h @@ -20,12 +20,10 @@ /* - * Initialization sequence for the application or library GOT. + * Initialization sequence for the application/library GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ do { \ - Elf32_Sym *sym; \ - char *strtab; \ unsigned long i; \ \ /* Check if this is the dynamic linker itself */ \ @@ -41,43 +39,6 @@ do { \ while (i < MODULE->mips_local_gotno) \ GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \ \ - /* Handle global GOT entries */ \ - GOT_BASE += MODULE->mips_local_gotno; \ - sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] + \ - (unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym; \ - strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] + \ - (unsigned long) MODULE->loadaddr); \ - i = MODULE->mips_symtabno - MODULE->mips_gotsym; \ - while (i--) { \ - if (sym->st_shndx == SHN_UNDEF) { \ - if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ - sym->st_value) \ - *GOT_BASE = sym->st_value + \ - (unsigned long) MODULE->loadaddr; \ - else { \ - *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - 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, 1); \ - } \ - else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ - *GOT_BASE != sym->st_value) \ - *GOT_BASE += (unsigned long) MODULE->loadaddr; \ - else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \ - if (sym->st_other == 0) \ - *GOT_BASE += (unsigned long) MODULE->loadaddr; \ - } \ - else { \ - *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 1); \ - } \ - \ - ++GOT_BASE; \ - ++sym; \ - } \ } while (0) diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index e6c3781b8..5b1192169 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -142,3 +142,62 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt, }; return 0; } + +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) +{ + Elf32_Sym *sym; + char *strtab; + unsigned long i; + unsigned long *got_entry; + + for (; tpnt ; tpnt = tpnt->next) { + + /* We don't touch the dynamic linker */ + if (tpnt->libtype == program_interpreter) + continue; + + /* Setup the loop variables */ + got_entry = (unsigned long *) (tpnt->loadaddr + + tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno; + sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + + (unsigned long) tpnt->loadaddr) + tpnt->mips_gotsym; + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + + (unsigned long) tpnt->loadaddr); + i = tpnt->mips_symtabno - tpnt->mips_gotsym; + + /* Relocate the global GOT entries for the object */ + while(i--) { + if (sym->st_shndx == SHN_UNDEF) { + if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value) + *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr; + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, NULL, 1); + } + } + else if (sym->st_shndx == SHN_COMMON) { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, NULL, 1); + } + else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && + *got_entry != sym->st_value) + *got_entry += (unsigned long) tpnt->loadaddr; + else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { + if (sym->st_other == 0) + *got_entry += (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, NULL, 1); + } + +#ifdef DL_DEBUG + if (*got_entry == 0) + _dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name); +#endif + + got_entry++; + sym++; + } + } +} diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h index 9d48d8f73..a669bba67 100644 --- a/ldso/ldso/mips/ld_sysdep.h +++ b/ldso/ldso/mips/ld_sysdep.h @@ -20,12 +20,10 @@ /* - * Initialization sequence for the application or library GOT. + * Initialization sequence for the application/library GOT. */ #define INIT_GOT(GOT_BASE,MODULE) \ do { \ - Elf32_Sym *sym; \ - char *strtab; \ unsigned long i; \ \ /* Check if this is the dynamic linker itself */ \ @@ -41,43 +39,6 @@ do { \ while (i < MODULE->mips_local_gotno) \ GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \ \ - /* Handle global GOT entries */ \ - GOT_BASE += MODULE->mips_local_gotno; \ - sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] + \ - (unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym; \ - strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] + \ - (unsigned long) MODULE->loadaddr); \ - i = MODULE->mips_symtabno - MODULE->mips_gotsym; \ - while (i--) { \ - if (sym->st_shndx == SHN_UNDEF) { \ - if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ - sym->st_value) \ - *GOT_BASE = sym->st_value + \ - (unsigned long) MODULE->loadaddr; \ - else { \ - *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - 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, 1); \ - } \ - else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \ - *GOT_BASE != sym->st_value) \ - *GOT_BASE += (unsigned long) MODULE->loadaddr; \ - else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \ - if (sym->st_other == 0) \ - *GOT_BASE += (unsigned long) MODULE->loadaddr; \ - } \ - else { \ - *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \ - sym->st_name, MODULE->symbol_scope, NULL, 1); \ - } \ - \ - ++GOT_BASE; \ - ++sym; \ - } \ } while (0) diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c index ebb0aec56..1bbb79364 100644 --- a/ldso/ldso/readelflib1.c +++ b/ldso/ldso/readelflib1.c @@ -527,14 +527,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, #if defined(__mips__) { - int i = 1; - Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; + int i = 1; + Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr; - while(dpnt->d_tag) { - dpnt++; - i++; - } - dynamic_size = i * sizeof(Elf32_Dyn); + while(dpnt->d_tag) { + dpnt++; + i++; + } + dynamic_size = i; } #endif -- cgit v1.2.3