about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mips/dl-machine.h64
-rw-r--r--sysdeps/mips/mips64/dl-machine.h61
2 files changed, 69 insertions, 56 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	      \
diff --git a/sysdeps/mips/mips64/dl-machine.h b/sysdeps/mips/mips64/dl-machine.h
index c2f2f6e939..024476b66b 100644
--- a/sysdeps/mips/mips64/dl-machine.h
+++ b/sysdeps/mips/mips64/dl-machine.h
@@ -252,9 +252,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)
     {
@@ -264,45 +264,52 @@ 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;
+		}
+	      this++;
+	    }
+	}
     }
 
     {
       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))
 	    {
-	      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");