summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/dl-elf.c37
-rw-r--r--ldso/ldso/dl-hash.c18
-rw-r--r--ldso/ldso/hash.c18
-rw-r--r--ldso/ldso/ldso.c71
-rw-r--r--ldso/ldso/mips/dl-sysdep.h8
-rw-r--r--ldso/ldso/mips/ld_sysdep.h8
-rw-r--r--ldso/ldso/mips/resolve.S14
-rw-r--r--ldso/ldso/readelflib1.c37
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);
};