about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-libc.c2
-rw-r--r--elf/dl-load.c13
-rw-r--r--elf/dl-lookup.c18
-rw-r--r--elf/dl-reloc.c8
-rw-r--r--elf/dl-runtime.c56
-rw-r--r--elf/dl-sym.c39
-rw-r--r--elf/dl-symbol.c8
-rw-r--r--elf/elf.h80
-rw-r--r--elf/rtld.c24
9 files changed, 181 insertions, 67 deletions
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index 39ccf82ed1..07aae9c8f9 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -65,7 +65,7 @@ struct do_dlsym_args
   const char *name;
 
   /* Return values of do_dlsym.  */
-  ElfW(Addr) loadbase;
+  lookup_t loadbase;
   const ElfW(Sym) *ref;
 };
 
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0291bf2a74..f5d91ba6c7 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -917,11 +917,14 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 	   As a refinement, sometimes we have an address that we would
 	   prefer to map such objects at; but this is only a preference,
 	   the OS can do whatever it likes. */
- 	caddr_t mapat;
 	ElfW(Addr) mappref;
 	mappref = (ELF_PREFERRED_ADDRESS (loader, maplength, c->mapstart)
 		   - MAP_BASE_ADDR (l));
-	mapat = map_segment (mappref, maplength, c->prot, 0, c->mapoff);
+
+	/* Remember which part of the address space this object uses.  */
+	l->l_map_start = map_segment (mappref, maplength, c->prot, 0,
+				      c->mapoff);
+	l->l_map_end = l->l_map_start + maplength;
 	l->l_addr = (ElfW(Addr)) mapat - c->mapstart;
 
 	/* Change protection on the excess portion to disallow all access;
@@ -929,14 +932,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
 	   unallocated.  Then jump into the normal segment-mapping loop to
 	   handle the portion of the segment past the end of the file
 	   mapping.  */
-	__mprotect ((caddr_t) (l->l_addr + c->mapend),
+	__mprotect ((caddr_t) l->l_map_start,
 		    loadcmds[nloadcmds - 1].allocend - c->mapend,
 		    0);
 
-	/* Remember which part of the address space this object uses.  */
-	l->l_map_start = c->mapstart + l->l_addr;
-	l->l_map_end = l->l_map_start + maplength;
-
 	goto postmap;
       }
     else
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index dc4564f2c7..c38e2e81f7 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -86,7 +86,7 @@ static int
 add_dependency (struct link_map *undef_map, struct link_map *map)
 {
   struct link_map **list;
-  unsigned act;
+  unsigned int act;
   unsigned int i;
   int result = 0;
 
@@ -183,7 +183,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
 /* Search loaded objects' symbol tables for a definition of the symbol
    UNDEF_NAME.  */
 
-ElfW(Addr)
+lookup_t
 internal_function
 _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 		   const ElfW(Sym) **ref, struct r_scope_elem *symbol_scope[],
@@ -241,7 +241,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
 		       ": symbol `", undef_name, "'\n", NULL);
 
   *ref = current_value.s;
-  return current_value.m->l_addr;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -250,7 +250,7 @@ _dl_lookup_symbol (const char *undef_name, struct link_map *undef_map,
    it only considers objects which were loaded after the described
    object.  If there are more search lists the object described by
    SKIP_MAP is only skipped.  */
-ElfW(Addr)
+lookup_t
 internal_function
 _dl_lookup_symbol_skip (const char *undef_name,
 			struct link_map *undef_map, const ElfW(Sym) **ref,
@@ -328,7 +328,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
 		       ": symbol `", undef_name, "' (skip)\n", NULL);
 
   *ref = current_value.s;
-  return current_value.m->l_addr;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
@@ -337,7 +337,7 @@ _dl_lookup_symbol_skip (const char *undef_name,
    symbol.
 
    XXX We'll see whether we need this separate function.  */
-ElfW(Addr)
+lookup_t
 internal_function
 _dl_lookup_versioned_symbol (const char *undef_name,
 			     struct link_map *undef_map, const ElfW(Sym) **ref,
@@ -422,13 +422,13 @@ _dl_lookup_versioned_symbol (const char *undef_name,
 		       "]\n", NULL);
 
   *ref = current_value.s;
-  return current_value.m->l_addr;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
 /* Similar to _dl_lookup_symbol_skip but takes an additional argument
    with the version we are looking for.  */
-ElfW(Addr)
+lookup_t
 internal_function
 _dl_lookup_versioned_symbol_skip (const char *undef_name,
 				  struct link_map *undef_map,
@@ -523,7 +523,7 @@ _dl_lookup_versioned_symbol_skip (const char *undef_name,
 		       "] (skip)\n", NULL);
 
   *ref = current_value.s;
-  return current_value.m->l_addr;
+  return LOOKUP_VALUE (current_value.m);
 }
 
 
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 4c7aabea85..d1537ec3dc 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -70,6 +70,14 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
     const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 
     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
+#define RESOLVE_MAP(ref, version, flags) \
+    (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL			      \
+     ? ((version) != NULL && (version)->hash != 0			      \
+	? _dl_lookup_versioned_symbol (strtab + (*ref)->st_name, l, (ref),    \
+				       scope, (version), (flags))	      \
+	: _dl_lookup_symbol (strtab + (*ref)->st_name, l, (ref), scope,	      \
+			     (flags)))					      \
+     : l)
 #define RESOLVE(ref, version, flags) \
     (__builtin_expect (ELFW(ST_VISIBILITY) ((*ref)->st_other), 0) == 0	      \
      ? ((version) != NULL && (version)->hash != 0			      \
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index d76b513a27..6237afce07 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -57,6 +57,7 @@ fixup (
     = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
   const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
   void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
+  lookup_t result;
   ElfW(Addr) value;
 
   /* The use of `alloca' here looks ridiculous but it helps.  The goal is
@@ -83,33 +84,38 @@ fixup (
 
 	    if (version->hash != 0)
 	      {
-		value = _dl_lookup_versioned_symbol(strtab + sym->st_name, l,
-						    &sym, l->l_scope, version,
-						    ELF_MACHINE_JMP_SLOT);
+		result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
+						      l, &sym, l->l_scope,
+						      version,
+						      ELF_MACHINE_JMP_SLOT);
 		break;
 	      }
 	  }
 	case 0:
-	  value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
-				     l->l_scope, ELF_MACHINE_JMP_SLOT);
+	  result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
+				      l->l_scope, ELF_MACHINE_JMP_SLOT);
 	}
 
-      /* Currently value contains the base load address of the object
-	 that defines sym.  Now add in the symbol offset.  */
-      value = (sym ? value + sym->st_value : 0);
+      /* Currently result contains the base load address (or link map)
+	 of the object that defines sym.  Now add in the symbol
+	 offset.  */
+      value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
     }
   else
+    {
     /* We already found the symbol.  The module (and therefore its load
        address) is also known.  */
-    value = l->l_addr + sym->st_value;
+      value = l->l_addr + sym->st_value;
+#ifdef DL_LOOKUP_RETURNS_MAP
+      result = l;
+#endif
+    }
 
   /* And now perhaps the relocation addend.  */
   value = elf_machine_plt_value (l, reloc, value);
 
   /* Finally, fix up the plt itself.  */
-  elf_machine_fixup_plt (l, reloc, rel_addr, value);
-
-  return value;
+  return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
 }
 #endif
 
@@ -124,6 +130,7 @@ profile_fixup (
 {
   void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
   ElfW(Addr) *resultp;
+  lookup_t result;
   ElfW(Addr) value;
 
   /* The use of `alloca' here looks ridiculous but it helps.  The goal is
@@ -166,27 +173,32 @@ profile_fixup (
 
 		if (version->hash != 0)
 		  {
-		    value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
-							l, &sym, l->l_scope,
-							version,
-							ELF_MACHINE_JMP_SLOT);
+		    result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
+							 l, &sym, l->l_scope,
+							 version,
+							 ELF_MACHINE_JMP_SLOT);
 		    break;
 		  }
 	      }
 	    case 0:
-	      value = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
-					 l->l_scope, ELF_MACHINE_JMP_SLOT);
+	      result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
+					  l->l_scope, ELF_MACHINE_JMP_SLOT);
 	    }
 
-	  /* Currently value contains the base load address of the object
-	     that defines sym.  Now add in the symbol offset.  */
-	  value = (sym ? value + sym->st_value : 0);
+	  /* Currently result contains the base load address (or link map)
+	     of the object that defines sym.  Now add in the symbol
+	     offset.  */
+	  value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
 	}
       else
+	{
 	/* We already found the symbol.  The module (and therefore its load
 	   address) is also known.  */
 	value = l->l_addr + sym->st_value;
-
+#ifdef DL_LOOKUP_RETURNS_MAP
+	result = l;
+#endif
+	}
       /* And now perhaps the relocation addend.  */
       value = elf_machine_plt_value (l, reloc, value);
 
diff --git a/elf/dl-sym.c b/elf/dl-sym.c
index 80be9544cb..84236ff993 100644
--- a/elf/dl-sym.c
+++ b/elf/dl-sym.c
@@ -1,5 +1,5 @@
 /* Look up a symbol in a shared object loaded by `dlopen'.
-   Copyright (C) 1999 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -29,12 +29,12 @@ void *
 internal_function
 _dl_sym (void *handle, const char *name, void *who)
 {
-  ElfW(Addr) loadbase;
   const ElfW(Sym) *ref = NULL;
+  lookup_t result;
 
   if (handle == RTLD_DEFAULT)
     /* Search the global scope.  */
-    loadbase = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
+    result = _dl_lookup_symbol (name, NULL, &ref, _dl_global_scope, 0);
   else
     {
       struct link_map *l, *match;
@@ -56,8 +56,8 @@ _dl_sym (void *handle, const char *name, void *who)
 	       main program (we hope).  */
 	    match = _dl_loaded;
 
-	  loadbase = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
-					0);
+	  result = _dl_lookup_symbol (name, match, &ref, map->l_local_scope,
+				      0);
 	}
       else
 	{
@@ -69,13 +69,13 @@ RTLD_NEXT used in code not dynamically loaded"));
 	  while (l->l_loader)
 	    l = l->l_loader;
 
-	  loadbase = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
-					     match);
+	  result = _dl_lookup_symbol_skip (name, l, &ref, l->l_local_scope,
+					   match);
 	}
     }
 
-  if (loadbase)
-    return (void *) (loadbase + ref->st_value);
+  if (result)
+    return DL_SYMBOL_ADDRESS (result, ref);
 
   return NULL;
 }
@@ -84,9 +84,9 @@ void *
 internal_function
 _dl_vsym (void *handle, const char *name, const char *version, void *who)
 {
-  ElfW(Addr) loadbase;
   const ElfW(Sym) *ref = NULL;
   struct r_found_version vers;
+  lookup_t result;
 
   /* Compute hash value to the version string.  */
   vers.name = version;
@@ -97,8 +97,8 @@ _dl_vsym (void *handle, const char *name, const char *version, void *who)
 
   if (handle == RTLD_DEFAULT)
     /* Search the global scope.  */
-    loadbase = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
-					    &vers, 0);
+    result = _dl_lookup_versioned_symbol (name, NULL, &ref, _dl_global_scope,
+					  &vers, 0);
   else if (handle == RTLD_NEXT)
     {
       struct link_map *l, *match;
@@ -118,20 +118,19 @@ RTLD_NEXT used in code not dynamically loaded"));
       while (l->l_loader)
 	l = l->l_loader;
 
-      loadbase = _dl_lookup_versioned_symbol_skip (name, l, &ref,
-						   l->l_local_scope,
-						   &vers, match);
+      result = _dl_lookup_versioned_symbol_skip (name, l, &ref,
+						 l->l_local_scope,
+						 &vers, match);
     }
   else
     {
       /* Search the scope of the given object.  */
       struct link_map *map = handle;
-      loadbase = _dl_lookup_versioned_symbol (name, map, &ref,
-					      map->l_local_scope, &vers, 0);
+      result = _dl_lookup_versioned_symbol (name, map, &ref,
+					    map->l_local_scope, &vers, 0);
     }
 
-  if (loadbase)
-    return (void *) (loadbase + ref->st_value);
-
+  if (result)
+    return DL_SYMBOL_ADDRESS (result, ref);
   return NULL;
 }
diff --git a/elf/dl-symbol.c b/elf/dl-symbol.c
index 136b10a2b5..bdd7615e48 100644
--- a/elf/dl-symbol.c
+++ b/elf/dl-symbol.c
@@ -1,5 +1,5 @@
 /* Look up a symbol's run-time value in the scope of a loaded object.
-   Copyright (C) 1995,96,98,99,2000 Free Software Foundation, Inc.
+   Copyright (C) 1995, 96, 98, 99, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -26,8 +26,8 @@ ElfW(Addr)
 internal_function
 _dl_symbol_value (struct link_map *map, const char *name)
 {
-  ElfW(Addr) loadbase;
   const ElfW(Sym) *ref = NULL;
-  loadbase = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
-  return loadbase + ref->st_value;
+  lookup_t result;
+  result = _dl_lookup_symbol (name, map, &ref, map->l_local_scope, 0);
+  return (result ? LOOKUP_VALUE_ADDRESS (result) : 0) + ref->st_value;
 }
diff --git a/elf/elf.h b/elf/elf.h
index b843011312..042dcbdb31 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1757,6 +1757,86 @@ typedef Elf32_Addr Elf32_Conflict;
 /* Keep this the last entry.  */
 #define R_ARM_NUM		256
 
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS		0x0000000f	/* os-specific flags */
+#define EF_IA_64_ABI64		0x00000010	/* 64-bit ABI */
+#define EF_IA_64_ARCH		0xff000000	/* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT	(PT_LOPROC + 0)	/* arch extension bits */
+#define PT_IA_64_UNWIND		(PT_LOPROC + 1)	/* ia64 unwind bits */
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV	0x80000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT		(SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND	(SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT		0x10000000	/* section near gp */
+#define SHF_IA_64_NORECOV	0x20000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE	(DT_LOPROC + 0)
+#define DT_IA_64_NUM		1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE		0x00	/* none */
+#define R_IA64_IMM14		0x21	/* symbol + addend, add imm14 */
+#define R_IA64_IMM22		0x22	/* symbol + addend, add imm22 */
+#define R_IA64_IMM64		0x23	/* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB		0x24	/* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB		0x25	/* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB		0x26	/* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB		0x27	/* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22		0x2a	/* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I		0x2b	/* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL64MSB	0x2e	/* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB	0x2f	/* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22		0x32	/* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I		0x33	/* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22		0x3a	/* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I	0x3b	/* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB	0x3e	/* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB	0x3f	/* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I		0x43	/* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB	0x44	/* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB	0x45	/* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB	0x46	/* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB	0x47	/* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL21B		0x49	/* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M		0x4a	/* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F		0x4b	/* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB	0x4c	/* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB	0x4d	/* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB	0x4e	/* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB	0x4f	/* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22	0x52	/* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I	0x53	/* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_SEGREL32MSB	0x5c	/* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB	0x5d	/* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB	0x5e	/* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB	0x5f	/* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB	0x64	/* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB	0x65	/* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB	0x66	/* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB	0x67	/* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB		0x6c	/* data 4 + REL */
+#define R_IA64_REL32LSB		0x6d	/* data 4 + REL */
+#define R_IA64_REL64MSB		0x6e	/* data 8 + REL */
+#define R_IA64_REL64LSB		0x6f	/* data 8 + REL */
+#define R_IA64_LTV32MSB		0x70	/* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB		0x71	/* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB		0x72	/* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB		0x73	/* symbol + addend, data8 LSB */
+#define R_IA64_IPLTMSB		0x80	/* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB		0x81	/* dynamic reloc, imported PLT, LSB */
+#define R_IA64_LTOFF22X		0x86	/* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV		0x87	/* Use of LTOFF22X.  */
+
 __END_DECLS
 
 #endif	/* elf.h */
diff --git a/elf/rtld.c b/elf/rtld.c
index c3363ade31..5c3dd43abf 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -160,6 +160,8 @@ _dl_start (void *arg)
   /* This #define produces dynamic linking inline functions for
      bootstrap relocation instead of general-purpose relocation.  */
 #define RTLD_BOOTSTRAP
+#define RESOLVE_MAP(sym, version, flags) \
+  ((*(sym))->st_shndx == SHN_UNDEF ? 0 : &bootstrap_map)
 #define RESOLVE(sym, version, flags) \
   ((*(sym))->st_shndx == SHN_UNDEF ? 0 : bootstrap_map.l_addr)
 #include "dynamic-link.h"
@@ -200,7 +202,15 @@ _dl_start (void *arg)
      header table in core.  Put the rest of _dl_start into a separate
      function, that way the compiler cannot put accesses to the GOT
      before ELF_DYNAMIC_RELOCATE.  */
-  return _dl_start_final (arg, &bootstrap_map, start_time);
+  {
+    ElfW(Addr) entry = _dl_start_final (arg, &bootstrap_map, start_time);
+
+#ifndef ELF_MACHINE_START_ADDRESS
+# define ELF_MACHINE_START_ADDRESS(map, start) (start)
+#endif
+
+    return ELF_MACHINE_START_ADDRESS (_dl_loaded, entry);
+  }
 }
 
 
@@ -886,10 +896,16 @@ of this helper program; chances are you did not intend to run this program.\n\
 	for (i = 1; i < _dl_argc; ++i)
 	  {
 	    const ElfW(Sym) *ref = NULL;
-	    ElfW(Addr) loadbase = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
-						     &ref, _dl_loaded->l_scope,
-						     ELF_MACHINE_JMP_SLOT);
+	    ElfW(Addr) loadbase;
+	    lookup_t result;
 	    char buf[20], *bp;
+
+	    result = _dl_lookup_symbol (_dl_argv[i], _dl_loaded,
+					&ref, _dl_loaded->l_scope,
+					ELF_MACHINE_JMP_SLOT);
+
+	    loadbase = LOOKUP_VALUE_ADDRESS (result);
+
 	    buf[sizeof buf - 1] = '\0';
 	    bp = _itoa_word (ref->st_value, &buf[sizeof buf - 1], 16, 0);
 	    while ((size_t) (&buf[sizeof buf - 1] - bp) < sizeof loadbase * 2)