diff options
Diffstat (limited to 'sysdeps/mips/dl-machine.h')
-rw-r--r-- | sysdeps/mips/dl-machine.h | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h index 965cef9c8d..19cdd245fe 100644 --- a/sysdeps/mips/dl-machine.h +++ b/sysdeps/mips/dl-machine.h @@ -18,6 +18,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* FIXME: Profiling of shared libraries is not implemented yet. */ #ifndef dl_machine_h #define dl_machine_h @@ -31,6 +32,10 @@ #error ENTRY_POINT needs to be defined for MIPS. #endif +/* The offset of gp from GOT might be system-dependent. It's set by + ld. The same value is also */ +#define OFFSET_GP_GOT 0x7ff0 + #ifndef _RTLD_PROLOGUE # define _RTLD_PROLOGUE(entry) "\n\t.globl " #entry \ "\n\t.ent " #entry \ @@ -95,7 +100,7 @@ static inline ElfW(Addr) * elf_mips_got_from_gpreg (ElfW(Addr) gpreg) { /* FIXME: the offset of gp from GOT may be system-dependent. */ - return (ElfW(Addr) *) (gpreg - 0x7ff0); + return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT); } /* Return the link-time address of _DYNAMIC. Conveniently, this is the @@ -207,7 +212,7 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc) _dl_runtime_resolve. MIPS instead calls __dl_runtime_resolve. We have to use our own version because of the way the got section is treaded on MIPS (we've also got ELF_MACHINE_PLT defined). */ - + #define ELF_MACHINE_RUNTIME_TRAMPOLINE \ /* The flag _dl_mips_gnu_objects is set if all dynamic objects are \ generated by the gnu linker. */ \ @@ -235,12 +240,9 @@ __dl_runtime_resolve (ElfW(Word) sym_index, \ = (const ElfW(Word)) l->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; \ const ElfW(Word) gotsym \ = (const ElfW(Word)) l->l_info[DT_MIPS (GOTSYM)]->d_un.d_val; \ - const ElfW(Sym) *sym; \ - ElfW(Addr) funcaddr; \ + const ElfW(Sym) *sym = &symtab[sym_index]; \ ElfW(Addr) value; \ \ - /* Look up the symbol's run-time value. */ \ - sym = &symtab[sym_index]; \ /* FIXME: The symbol versioning stuff is not tested yet. */ \ if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0) \ { \ @@ -279,7 +281,7 @@ __dl_runtime_resolve (ElfW(Word) sym_index, \ /* Apply the relocation with that value. */ \ *(got + local_gotno + sym_index - gotsym) = value; \ \ - return value; \ + return value; \ } \ \ asm ("\n \ @@ -291,6 +293,7 @@ asm ("\n \ _dl_runtime_resolve:\n \ .set noreorder\n \ # Save slot call pc.\n \ + # XXX: Is this ok? \ move $3, $31\n \ # Modify t9 ($25) so as to point .cpload instruction.\n \ addu $25,8\n \ @@ -362,6 +365,7 @@ _RTLD_PROLOGUE(ENTRY_POINT)\ # the address of the dynamic structure. Though MIPS ABI\n\ # doesn't say nothing about this, I emulate this here.\n\ la $4, _DYNAMIC\n\ + # Subtract OFFSET_GP_GOT\n\ sw $4, -0x7ff0($28)\n\ move $4, $29\n\ subu $29, 16\n\ @@ -485,7 +489,9 @@ elf_machine_got_rel (struct link_map *map, int lazy) ElfW(Addr) *got; ElfW(Sym) *sym; int i, n, symidx; +#ifndef RTLD_BOOTSTRAP const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); +#endif /* This function is loaded in dl-reloc as a nested function and can therefore access the variable scope from _dl_relocate_object. */ #ifdef RTLD_BOOTSTRAP @@ -531,12 +537,12 @@ elf_machine_got_rel (struct link_map *map, int lazy) i = (got[1] & ELF_MIPS_GNU_GOT1_MASK)? 2: 1; n = map->l_info[DT_MIPS (LOCAL_GOTNO)]->d_un.d_val; /* Add the run-time display to all local got entries if needed. */ - if (map->l_addr != 0) + if (__builtin_expect (map->l_addr != 0, 0)) { while (i < n) got[i++] += map->l_addr; } - + /* Handle global got entries. */ got += n; /* Keep track of the symbol index. */ @@ -544,19 +550,16 @@ elf_machine_got_rel (struct link_map *map, int lazy) sym = (ElfW(Sym) *) D_PTR (map, l_info[DT_SYMTAB]) + symidx; i = (map->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val - map->l_info[DT_MIPS (GOTSYM)]->d_un.d_val); - + + /* This loop doesn't handle Quickstart. */ while (i--) { if (sym->st_shndx == SHN_UNDEF) { - if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC) - { - if (sym->st_value && lazy) - *got = sym->st_value + map->l_addr; - else - *got = RESOLVE_GOTSYM (sym, symidx); - } - else /* if (*got == 0 || *got == QS) */ + if (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC + && sym->st_value && lazy) + *got = sym->st_value + map->l_addr; + else *got = RESOLVE_GOTSYM (sym, symidx); } else if (sym->st_shndx == SHN_COMMON) |