diff options
Diffstat (limited to 'sysdeps/mips/dl-machine.h')
-rw-r--r-- | sysdeps/mips/dl-machine.h | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h index f08afa9c7f..e1b9163526 100644 --- a/sysdeps/mips/dl-machine.h +++ b/sysdeps/mips/dl-machine.h @@ -141,9 +141,9 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc) extern int _dl_mips_gnu_objects; /* got[1] is reserved to keep its link map address for the shared - object generated by gnu linker. If all are such object, we can - find link map from current GPREG simply. If not so, get link map - for callers object containing STUB_PC. */ + object generated by the gnu linker. If all are such objects, we + can find the link map from current GPREG simply. If not so, get + the link map for caller's object containing STUB_PC. */ if (_dl_mips_gnu_objects) { @@ -153,45 +153,51 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc) g1 = ((ElfW(Word) *) got)[1]; if ((g1 & ELF_MIPS_GNU_GOT1_MASK) != 0) - return (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK); + { + struct link_map *l = + (struct link_map *) (g1 & ~ELF_MIPS_GNU_GOT1_MASK); + ElfW(Addr) base, limit; + const ElfW(Phdr) *p = l->l_phdr; + ElfW(Half) this, nent = l->l_phnum; + + /* For the common case of a stub being called from the containing + object, STUB_PC will point to somewhere within the object that + is described by the link map fetched via got[1]. Otherwise we + have to scan all maps. */ + for (this = 0; this < nent; this++) + { + if (p[this].p_type == PT_LOAD) + { + base = p[this].p_vaddr + l->l_addr; + limit = base + p[this].p_memsz; + if (stub_pc >= base && stub_pc < limit) + return l; + } + } + } } { struct link_map *l = _dl_loaded; - struct link_map *ret = 0; - ElfW(Addr) candidate = 0; while (l) { - ElfW(Addr) base = 0; + ElfW(Addr) base, limit; const ElfW(Phdr) *p = l->l_phdr; ElfW(Half) this, nent = l->l_phnum; - /* Get the base. */ - for (this = 0; this < nent; this++) - if (p[this].p_type == PT_LOAD) - { - base = p[this].p_vaddr + l->l_addr; - break; - } - if (! base) - { - l = l->l_next; - continue; - } - - /* Find closest link base addr. */ - if ((base < stub_pc) && (candidate < base)) + for (this = 0; this < nent; ++this) { - candidate = base; - ret = l; + if (p[this].p_type == PT_LOAD) + { + base = p[this].p_vaddr + l->l_addr; + limit = base + p[this].p_memsz; + if (stub_pc >= base && stub_pc < limit) + return l; + } } l = l->l_next; } - if (candidate && ret && (candidate < stub_pc)) - return ret; - else if (!candidate) - return _dl_loaded; } _dl_signal_error (0, NULL, "cannot find runtime link map"); @@ -208,7 +214,7 @@ elf_machine_runtime_link_map (ElfW(Addr) gpreg, ElfW(Addr) stub_pc) Other architectures call fixup from dl-runtime.c in _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). */ + treated 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 \ |