]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/sparc/sparc64/dl-machine.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / sparc / sparc64 / dl-machine.h
index b4785c74ccdf09377bfeaba5a4a9cbc2b9cdf6d6..713aeb7734293689a654d1585eeecd5a00de47d3 100644 (file)
@@ -1,21 +1,23 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  Sparc64 version.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 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
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
    The GNU C Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef dl_machine_h
+#define dl_machine_h
 
 #define ELF_MACHINE_NAME "sparc64"
 
@@ -23,6 +25,7 @@
 #include <sys/param.h>
 #include <ldsodefs.h>
 #include <sysdep.h>
+#include <dl-plt.h>
 
 #define ELF64_R_TYPE_ID(info)  ((info) & 0xff)
 #define ELF64_R_TYPE_DATA(info) ((info) >> 8)
@@ -34,6 +37,18 @@ elf_machine_matches_host (const Elf64_Ehdr *ehdr)
   return ehdr->e_machine == EM_SPARCV9;
 }
 
+/* We have to do this because elf_machine_{dynamic,load_address} can be
+   invoked from functions that have no GOT references, and thus the compiler
+   has no obligation to load the PIC register.  */
+#define LOAD_PIC_REG(PIC_REG)  \
+do {   Elf64_Addr tmp;         \
+       __asm("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+             "rd %%pc, %0\n\t" \
+             "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \
+             "add %0, %1, %0" \
+             : "=r" (PIC_REG), "=r" (tmp)); \
+} while (0)
+
 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
    first element of the GOT.  This must be inlined in a function which
    uses global data.  */
@@ -42,6 +57,8 @@ elf_machine_dynamic (void)
 {
   register Elf64_Addr *elf_pic_register __asm__("%l7");
 
+  LOAD_PIC_REG (elf_pic_register);
+
   return *elf_pic_register;
 }
 
@@ -49,137 +66,310 @@ elf_machine_dynamic (void)
 static inline Elf64_Addr
 elf_machine_load_address (void)
 {
-  register Elf64_Addr elf_pic_register __asm__("%l7");
-  Elf64_Addr pc, la;
-
-  /* Utilize the fact that a local .got entry will be partially
-     initialized at startup awaiting its RELATIVE fixup.  */
-
-  __asm("sethi %%hi(.Load_address), %1\n"
-       ".Load_address:\n\t"
-       "rd %%pc, %0\n\t"
-       "or %1, %%lo(.Load_address), %1\n\t"
-       : "=r"(pc), "=r"(la));
-
-  return pc - *(Elf64_Addr *)(elf_pic_register + la);
+  register Elf32_Addr *pc __asm ("%o7");
+  register Elf64_Addr *got __asm ("%l7");
+
+  __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"
+        "call 1f\n\t"
+        " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"
+        "call _DYNAMIC\n\t"
+        "call _GLOBAL_OFFSET_TABLE_\n"
+        "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));
+
+  /* got is now l_addr + _GLOBAL_OFFSET_TABLE_
+     *got is _DYNAMIC
+     pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8
+     pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12  */
+  return (Elf64_Addr) got - *got + (Elf32_Sword) ((pc[2] - pc[3]) * 4) - 4;
 }
 
-/* We have 4 cases to handle.  And we code different code sequences
-   for each one.  I love V9 code models...  */
-static inline Elf64_Addr
+static inline Elf64_Addr __attribute__ ((always_inline))
 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
                       const Elf64_Rela *reloc,
                       Elf64_Addr *reloc_addr, Elf64_Addr value)
 {
-  unsigned int *insns = (unsigned int *) reloc_addr;
-  Elf64_Addr plt_vaddr = (Elf64_Addr) reloc_addr;
+  sparc64_fixup_plt (map, reloc, reloc_addr, value + reloc->r_addend,
+                    reloc->r_addend, 1);
+  return value;
+}
+
+/* Return the final value of a plt relocation.  */
+static inline Elf64_Addr
+elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
+                      Elf64_Addr value)
+{
+  /* Don't add addend here, but in elf_machine_fixup_plt instead.
+     value + reloc->r_addend is the value which should actually be
+     stored into .plt data slot.  */
+  return value;
+}
 
-  /* Now move plt_vaddr up to the call instruction.  */
-  plt_vaddr += (2 * 4);
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_COPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SPARC_JMP_SLOT                                                      \
+     || ((type) >= R_SPARC_TLS_GD_HI22 && (type) <= R_SPARC_TLS_TPOFF64))     \
+    * ELF_RTYPE_CLASS_PLT)                                                   \
+   | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
 
-  /* PLT entries .PLT32768 and above look always the same.  */
-  if (__builtin_expect (reloc->r_addend, 0) != 0)
-    {
-      *reloc_addr = value - map->l_addr;
-    }
-  /* 32-bit Sparc style, the target is in the lower 32-bits of
-     address space.  */
-  else if ((value >> 32) == 0)
-    {
-      /* sethi %hi(target), %g1
-        jmpl   %g1 + %lo(target), %g0  */
+/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
+#define ELF_MACHINE_JMP_SLOT   R_SPARC_JMP_SLOT
 
-      insns[2] = 0x81c06000 | (value & 0x3ff);
-      __asm __volatile ("flush %0 + 8" : : "r" (insns));
+/* The SPARC never uses Elf64_Rel relocations.  */
+#define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
 
-      insns[1] = 0x03000000 | ((unsigned int)(value >> 10));
-      __asm __volatile ("flush %0 + 4" : : "r" (insns));
-    }
-  /* We can also get somewhat simple sequences if the distance between
-     the target and the PLT entry is within +/- 2GB.  */
-  else if ((plt_vaddr > value
-           && ((plt_vaddr - value) >> 32) == 0)
-          || (value > plt_vaddr
-              && ((value - plt_vaddr) >> 32) == 0))
+/* Set up the loaded object described by L so its unrelocated PLT
+   entries will jump to the on-demand fixup code in dl-runtime.c.  */
+
+static inline int
+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+{
+  if (l->l_info[DT_JMPREL] && lazy)
     {
-      unsigned int displacement;
+      extern void _dl_runtime_resolve_0 (void);
+      extern void _dl_runtime_resolve_1 (void);
+      extern void _dl_runtime_profile_0 (void);
+      extern void _dl_runtime_profile_1 (void);
+      Elf64_Addr res0_addr, res1_addr;
+      unsigned int *plt = (void *) D_PTR (l, l_info[DT_PLTGOT]);
 
-      if (plt_vaddr > value)
-       displacement = (0 - (plt_vaddr - value));
+      if (__builtin_expect(profile, 0))
+       {
+         res0_addr = (Elf64_Addr) &_dl_runtime_profile_0;
+         res1_addr = (Elf64_Addr) &_dl_runtime_profile_1;
+
+         if (GLRO(dl_profile) != NULL
+             && _dl_name_match_p (GLRO(dl_profile), l))
+           GL(dl_profile_map) = l;
+       }
       else
-       displacement = value - plt_vaddr;
+       {
+         res0_addr = (Elf64_Addr) &_dl_runtime_resolve_0;
+         res1_addr = (Elf64_Addr) &_dl_runtime_resolve_1;
+       }
 
-      /* mov   %o7, %g1
-        call   displacement
-         mov   %g1, %o7  */
+      /* PLT0 looks like:
 
-      insns[3] = 0x9e100001;
-      __asm __volatile ("flush %0 + 12" : : "r" (insns));
+        sethi  %uhi(_dl_runtime_{resolve,profile}_0), %g4
+        sethi  %hi(_dl_runtime_{resolve,profile}_0), %g5
+        or     %g4, %ulo(_dl_runtime_{resolve,profile}_0), %g4
+        or     %g5, %lo(_dl_runtime_{resolve,profile}_0), %g5
+        sllx   %g4, 32, %g4
+        add    %g4, %g5, %g5
+        jmpl   %g5, %g4
+         nop
+       */
 
-      insns[2] = 0x40000000 | (displacement >> 2);
-      __asm __volatile ("flush %0 + 8" : : "r" (insns));
+      plt[0] = 0x09000000 | (res0_addr >> (64 - 22));
+      plt[1] = 0x0b000000 | ((res0_addr >> 10) & 0x003fffff);
+      plt[2] = 0x88112000 | ((res0_addr >> 32) & 0x3ff);
+      plt[3] = 0x8a116000 | (res0_addr & 0x3ff);
+      plt[4] = 0x89293020;
+      plt[5] = 0x8a010005;
+      plt[6] = 0x89c14000;
+      plt[7] = 0x01000000;
 
-      insns[1] = 0x8210000f;
-      __asm __volatile ("flush %0 + 4" : : "r" (insns));
-    }
-  /* Worst case, ho hum...  */
-  else
-    {
-      unsigned int high32 = (value >> 32);
-      unsigned int low32 = (unsigned int) value;
+      /* PLT1 looks like:
 
-      /* ??? Some tricks can be stolen from the sparc64 egcs backend
-            constant formation code I wrote.  -DaveM  */
+        sethi  %uhi(_dl_runtime_{resolve,profile}_1), %g4
+        sethi  %hi(_dl_runtime_{resolve,profile}_1), %g5
+        or     %g4, %ulo(_dl_runtime_{resolve,profile}_1), %g4
+        or     %g5, %lo(_dl_runtime_{resolve,profile}_1), %g5
+        sllx   %g4, 32, %g4
+        add    %g4, %g5, %g5
+        jmpl   %g5, %g4
+         nop
+       */
 
-      /* sethi %hh(value), %g1
-        sethi  %lm(value), %g5
-        or     %g1, %hm(value), %g1
-        or     %g5, %lo(value), %g5
-        sllx   %g1, 32, %g1
-        jmpl   %g1 + %g5, %g0
-         nop  */
+      plt[8] = 0x09000000 | (res1_addr >> (64 - 22));
+      plt[9] = 0x0b000000 | ((res1_addr >> 10) & 0x003fffff);
+      plt[10] = 0x88112000 | ((res1_addr >> 32) & 0x3ff);
+      plt[11] = 0x8a116000 | (res1_addr & 0x3ff);
+      plt[12] = 0x89293020;
+      plt[13] = 0x8a010005;
+      plt[14] = 0x89c14000;
+      plt[15] = 0x01000000;
 
-      insns[6] = 0x81c04005;
-      __asm __volatile ("flush %0 + 24" : : "r" (insns));
+      /* Now put the magic cookie at the beginning of .PLT2
+        Entry .PLT3 is unused by this implementation.  */
+      *((struct link_map **)(&plt[16])) = l;
 
-      insns[5] = 0x83287020;
-      __asm __volatile ("flush %0 + 20" : : "r" (insns));
+      if (__builtin_expect (l->l_info[VALIDX(DT_GNU_PRELINKED)] != NULL, 0)
+         || __builtin_expect (l->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL, 0))
+       {
+         /* Need to reinitialize .plt to undo prelinking.  */
+         Elf64_Rela *rela = (Elf64_Rela *) D_PTR (l, l_info[DT_JMPREL]);
+         Elf64_Rela *relaend
+           = (Elf64_Rela *) ((char *) rela
+                             + l->l_info[DT_PLTRELSZ]->d_un.d_val);
+
+         /* prelink must ensure there are no R_SPARC_NONE relocs left
+            in .rela.plt.  */
+         while (rela < relaend)
+           {
+             if (__builtin_expect (rela->r_addend, 0) != 0)
+               {
+                 Elf64_Addr slot = ((rela->r_offset + l->l_addr + 0x400
+                                     - (Elf64_Addr) plt)
+                                    / 0x1400) * 0x1400
+                                   + (Elf64_Addr) plt - 0x400;
+                 /* ldx [%o7 + X], %g1  */
+                 unsigned int first_ldx = *(unsigned int *)(slot + 12);
+                 Elf64_Addr ptr = slot + (first_ldx & 0xfff) + 4;
+
+                 *(Elf64_Addr *) (rela->r_offset + l->l_addr)
+                   = (Elf64_Addr) plt
+                     - (slot + ((rela->r_offset + l->l_addr - ptr) / 8) * 24
+                        + 4);
+                 ++rela;
+                 continue;
+               }
+
+             *(unsigned int *) (rela->r_offset + l->l_addr)
+               = 0x03000000 | (rela->r_offset + l->l_addr - (Elf64_Addr) plt);
+             *(unsigned int *) (rela->r_offset + l->l_addr + 4)
+               = 0x30680000 | ((((Elf64_Addr) plt + 32 - rela->r_offset
+                                 - l->l_addr - 4) >> 2) & 0x7ffff);
+             __asm __volatile ("flush %0" : : "r" (rela->r_offset
+                                                   + l->l_addr));
+             __asm __volatile ("flush %0+4" : : "r" (rela->r_offset
+                                                     + l->l_addr));
+             ++rela;
+           }
+       }
+    }
 
-      insns[4] = 0x8a116000 | (low32 & 0x3ff);
-      __asm __volatile ("flush %0 + 16" : : "r" (insns));
+  return lazy;
+}
 
-      insns[3] = 0x82106000 | (high32 & 0x3ff);
-      __asm __volatile ("flush %0 + 12" : : "r" (insns));
+/* The PLT uses Elf64_Rela relocs.  */
+#define elf_machine_relplt elf_machine_rela
 
-      insns[2] = 0x0b000000 | (low32 >> 10);
-      __asm __volatile ("flush %0 + 8" : : "r" (insns));
+/* Undo the sub %sp, 6*8, %sp; add %sp, STACK_BIAS + 22*8, %o0 below
+   (but w/o STACK_BIAS) to get at the value we want in __libc_stack_end.  */
+#define DL_STACK_END(cookie) \
+  ((void *) (((long) (cookie)) - (22 - 6) * 8))
 
-      insns[1] = 0x03000000 | (high32 >> 10);
-      __asm __volatile ("flush %0 + 4" : : "r" (insns));
-    }
+/* Initial entry point code for the dynamic linker.
+   The C function `_dl_start' is the real entry point;
+   its return value is the user program's entry point.  */
 
-  return value;
-}
+#define RTLD_GOT_ADDRESS(pic_reg, reg, symbol) \
+       "sethi  %gdop_hix22(" #symbol "), " #reg "\n\t" \
+       "xor    " #reg ", %gdop_lox10(" #symbol "), " #reg "\n\t" \
+       "ldx    [" #pic_reg " + " #reg "], " #reg ", %gdop(" #symbol ")\n"
 
-/* Return the final value of a plt relocation.  */
-static inline Elf64_Addr
-elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
-                      Elf64_Addr value)
-{
-  return value + reloc->r_addend;
-}
+#define __S1(x)        #x
+#define __S(x) __S1(x)
 
-#ifdef RESOLVE
+#define RTLD_START __asm__ ( "\n"                                      \
+"      .text\n"                                                        \
+"      .global _start\n"                                               \
+"      .type   _start, @function\n"                                    \
+"      .align  32\n"                                                   \
+"_start:\n"                                                            \
+"   /* Make room for functions to drop their arguments on the stack.  */\n" \
+"      sub     %sp, 6*8, %sp\n"                                        \
+"   /* Pass pointer to argument block to _dl_start.  */\n"             \
+"      call    _dl_start\n"                                            \
+"       add     %sp," __S(STACK_BIAS) "+22*8,%o0\n"                    \
+"      /* FALLTHRU */\n"                                               \
+"      .size _start, .-_start\n"                                       \
+"\n"                                                                   \
+"      .global _dl_start_user\n"                                       \
+"      .type   _dl_start_user, @function\n"                            \
+"_dl_start_user:\n"                                                    \
+"   /* Load the GOT register.  */\n"                                   \
+"1:    call    11f\n"                                                  \
+"       sethi  %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n"               \
+"11:   or      %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n"          \
+"      add     %l7, %o7, %l7\n"                                        \
+"   /* Save the user entry point address in %l0.  */\n"                        \
+"      mov     %o0, %l0\n"                                             \
+"   /* See if we were run as a command with the executable file name as an\n" \
+"      extra leading argument.  If so, we must shift things around since we\n" \
+"      must keep the stack doubleword aligned.  */\n"                  \
+       RTLD_GOT_ADDRESS(%l7, %g5, _dl_skip_args)                       \
+"      ld      [%g5], %i0\n"                                           \
+"      brz,pt  %i0, 2f\n"                                              \
+"       ldx    [%sp + " __S(STACK_BIAS) " + 22*8], %i5\n"              \
+"      /* Find out how far to shift.  */\n"                            \
+"      sub     %i5, %i0, %i5\n"                                        \
+"      sllx    %i0, 3, %l6\n"                                          \
+       RTLD_GOT_ADDRESS(%l7, %l4, _dl_argv)                            \
+"      stx     %i5, [%sp + " __S(STACK_BIAS) " + 22*8]\n"              \
+"      add     %sp, " __S(STACK_BIAS) " + 23*8, %i1\n"                 \
+"      add     %i1, %l6, %i2\n"                                        \
+"      ldx     [%l4], %l5\n"                                           \
+"      /* Copy down argv.  */\n"                                       \
+"12:   ldx     [%i2], %i3\n"                                           \
+"      add     %i2, 8, %i2\n"                                          \
+"      stx     %i3, [%i1]\n"                                           \
+"      brnz,pt %i3, 12b\n"                                             \
+"       add    %i1, 8, %i1\n"                                          \
+"      sub     %l5, %l6, %l5\n"                                        \
+"      /* Copy down envp.  */\n"                                       \
+"13:   ldx     [%i2], %i3\n"                                           \
+"      add     %i2, 8, %i2\n"                                          \
+"      stx     %i3, [%i1]\n"                                           \
+"      brnz,pt %i3, 13b\n"                                             \
+"       add    %i1, 8, %i1\n"                                          \
+"      /* Copy down auxiliary table.  */\n"                            \
+"14:   ldx     [%i2], %i3\n"                                           \
+"      ldx     [%i2 + 8], %i4\n"                                       \
+"      add     %i2, 16, %i2\n"                                         \
+"      stx     %i3, [%i1]\n"                                           \
+"      stx     %i4, [%i1 + 8]\n"                                       \
+"      brnz,pt %i3, 14b\n"                                             \
+"       add    %i1, 16, %i1\n"                                         \
+"      stx     %l5, [%l4]\n"                                           \
+"  /* %o0 = _dl_loaded, %o1 = argc, %o2 = argv, %o3 = envp.  */\n"     \
+"2:\t" RTLD_GOT_ADDRESS(%l7, %o0, _rtld_local)                         \
+"      sllx    %i5, 3, %o3\n"                                          \
+"      add     %sp, " __S(STACK_BIAS) " + 23*8, %o2\n"                 \
+"      add     %o3, 8, %o3\n"                                          \
+"      mov     %i5, %o1\n"                                             \
+"      add     %o2, %o3, %o3\n"                                        \
+"      call    _dl_init\n"                                             \
+"       ldx    [%o0], %o0\n"                                           \
+"   /* Pass our finalizer function to the user in %g1.  */\n"          \
+       RTLD_GOT_ADDRESS(%l7, %g1, _dl_fini)                            \
+"  /* Jump to the user's entry point and deallocate the extra stack we got.  */\n" \
+"      jmp     %l0\n"                                                  \
+"       add    %sp, 6*8, %sp\n"                                        \
+"      .size   _dl_start_user, . - _dl_start_user\n"                   \
+"      .previous\n");
+
+#endif /* dl_machine_h */
+
+#define ARCH_LA_PLTENTER       sparc64_gnu_pltenter
+#define ARCH_LA_PLTEXIT                sparc64_gnu_pltexit
+
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
                  const Elf64_Sym *sym, const struct r_found_version *version,
-                 Elf64_Addr *const reloc_addr)
+                 void *const reloc_addr_arg, int skip_ifunc)
 {
-#ifndef RTLD_BOOTSTRAP
+  Elf64_Addr *const reloc_addr = reloc_addr_arg;
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+  const Elf64_Sym *const refsym = sym;
+#endif
+  Elf64_Addr value;
+  const unsigned long int r_type = ELF64_R_TYPE_ID (reloc->r_info);
+#if !defined RESOLVE_CONFLICT_FIND_MAP
+  struct link_map *sym_map = NULL;
+#endif
+
+#if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
   /* This is defined in rtld.c, but nowhere in the static libc.a; make the
      reference weak so static programs can still link.  This declaration
      cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
@@ -188,437 +378,302 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
   weak_extern (_dl_rtld_map);
 #endif
 
-  if (ELF64_R_TYPE_ID (reloc->r_info) == R_SPARC_RELATIVE)
+  if (__glibc_unlikely (r_type == R_SPARC_NONE))
+    return;
+
+  if (__glibc_unlikely (r_type == R_SPARC_SIZE64))
     {
-#ifndef RTLD_BOOTSTRAP
+      *reloc_addr = sym->st_size + reloc->r_addend;
+      return;
+    }
+
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
+  if (__glibc_unlikely (r_type == R_SPARC_RELATIVE))
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
       if (map != &_dl_rtld_map) /* Already done in rtld itself. */
+# endif
+       *reloc_addr += map->l_addr + reloc->r_addend;
+      return;
+    }
 #endif
-       *reloc_addr = map->l_addr + reloc->r_addend;
+
+#ifndef RESOLVE_CONFLICT_FIND_MAP
+  if (__builtin_expect (ELF64_ST_BIND (sym->st_info) == STB_LOCAL, 0)
+      && sym->st_shndx != SHN_UNDEF)
+    {
+      value = map->l_addr;
     }
-  else if (ELF64_R_TYPE_ID (reloc->r_info) != R_SPARC_NONE) /* Who is Wilbur? */
+  else
     {
-#ifndef RTLD_BOOTSTRAP
-      const Elf64_Sym *const refsym = sym;
+      sym_map = RESOLVE_MAP (&sym, version, r_type);
+      value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
+    }
+#else
+  value = 0;
 #endif
-      Elf64_Addr value;
-      if (sym->st_shndx != SHN_UNDEF &&
-         ELF64_ST_BIND (sym->st_info) == STB_LOCAL)
-       value = map->l_addr;
-      else
-       {
-         value = RESOLVE (&sym, version, ELF64_R_TYPE_ID (reloc->r_info));
-         if (sym)
-           value += sym->st_value;
-       }
-      value += reloc->r_addend;        /* Assume copy relocs have zero addend.  */
 
-      switch (ELF64_R_TYPE_ID (reloc->r_info))
+  value += reloc->r_addend;    /* Assume copy relocs have zero addend.  */
+
+  if (sym != NULL
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
+      && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+      && __builtin_expect (!skip_ifunc, 1))
+    value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
+
+  switch (r_type)
+    {
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+    case R_SPARC_COPY:
+      if (sym == NULL)
+       /* This can happen in trace mode if an object could not be
+          found.  */
+       break;
+      if (sym->st_size > refsym->st_size
+         || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))
        {
-#ifndef RTLD_BOOTSTRAP
-       case R_SPARC_COPY:
-         if (sym == NULL)
-           /* This can happen in trace mode if an object could not be
-              found.  */
-           break;
-         if (sym->st_size > refsym->st_size
-             || (_dl_verbose && sym->st_size < refsym->st_size))
-           {
-             extern char **_dl_argv;
-             const char *strtab;
+         const char *strtab;
 
-             strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
-             _dl_error_printf ("\
+         strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+         _dl_error_printf ("\
 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
-                               _dl_argv[0] ?: "<program name unknown>",
-                               strtab + refsym->st_name);
-           }
-         memcpy (reloc_addr, (void *) value, MIN (sym->st_size,
-                                                  refsym->st_size));
-         break;
+                           RTLD_PROGNAME, strtab + refsym->st_name);
+       }
+      memcpy (reloc_addr_arg, (void *) value,
+             MIN (sym->st_size, refsym->st_size));
+      break;
+#endif
+    case R_SPARC_64:
+    case R_SPARC_GLOB_DAT:
+      *reloc_addr = value;
+      break;
+    case R_SPARC_IRELATIVE:
+      value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
+      *reloc_addr = value;
+      break;
+    case R_SPARC_JMP_IREL:
+      value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
+      /* 'high' is always zero, for large PLT entries the linker
+        emits an R_SPARC_IRELATIVE.  */
+#ifdef RESOLVE_CONFLICT_FIND_MAP
+      sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
+#else
+      sparc64_fixup_plt (map, reloc, reloc_addr, value, 0, 0);
+#endif
+      break;
+    case R_SPARC_JMP_SLOT:
+#ifdef RESOLVE_CONFLICT_FIND_MAP
+      /* R_SPARC_JMP_SLOT conflicts against .plt[32768+]
+        relocs should be turned into R_SPARC_64 relocs
+        in .gnu.conflict section.
+        r_addend non-zero does not mean it is a .plt[32768+]
+        reloc, instead it is the actual address of the function
+        to call.  */
+      sparc64_fixup_plt (NULL, reloc, reloc_addr, value, 0, 0);
+#else
+      sparc64_fixup_plt (map, reloc, reloc_addr, value, reloc->r_addend, 0);
+#endif
+      break;
+#ifndef RESOLVE_CONFLICT_FIND_MAP
+    case R_SPARC_TLS_DTPMOD64:
+      /* Get the information from the link map returned by the
+        resolv function.  */
+      if (sym_map != NULL)
+       *reloc_addr = sym_map->l_tls_modid;
+      break;
+    case R_SPARC_TLS_DTPOFF64:
+      /* During relocation all TLS symbols are defined and used.
+        Therefore the offset is already correct.  */
+      *reloc_addr = (sym == NULL ? 0 : sym->st_value) + reloc->r_addend;
+      break;
+    case R_SPARC_TLS_TPOFF64:
+      /* The offset is negative, forward from the thread pointer.  */
+      /* We know the offset of object the symbol is contained in.
+        It is a negative value which will be added to the
+        thread pointer.  */
+      if (sym != NULL)
+       {
+         CHECK_STATIC_TLS (map, sym_map);
+         *reloc_addr = sym->st_value - sym_map->l_tls_offset
+           + reloc->r_addend;
+       }
+      break;
+# ifndef RTLD_BOOTSTRAP
+    case R_SPARC_TLS_LE_HIX22:
+    case R_SPARC_TLS_LE_LOX10:
+      if (sym != NULL)
+       {
+         CHECK_STATIC_TLS (map, sym_map);
+         value = sym->st_value - sym_map->l_tls_offset
+           + reloc->r_addend;
+         if (r_type == R_SPARC_TLS_LE_HIX22)
+           *(unsigned int *)reloc_addr =
+             ((*(unsigned int *)reloc_addr & 0xffc00000)
+              | (((~value) >> 10) & 0x3fffff));
+         else
+           *(unsigned int *)reloc_addr =
+             ((*(unsigned int *)reloc_addr & 0xffffe000) | (value & 0x3ff)
+              | 0x1c00);
+       }
+      break;
+# endif
 #endif
-       case R_SPARC_64:
-       case R_SPARC_GLOB_DAT:
-         *reloc_addr = value;
-         break;
 #ifndef RTLD_BOOTSTRAP
-       case R_SPARC_8:
-         *(char *) reloc_addr = value;
-         break;
-       case R_SPARC_16:
-         *(short *) reloc_addr = value;
-         break;
-       case R_SPARC_32:
-         *(unsigned int *) reloc_addr = value;
-         break;
-       case R_SPARC_DISP8:
-         *(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-         break;
-       case R_SPARC_DISP16:
-         *(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-         break;
-       case R_SPARC_DISP32:
-         *(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
-         break;
-       case R_SPARC_WDISP30:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & 0xc0000000) |
-            ((value - (Elf64_Addr) reloc_addr) >> 2));
-         break;
+    case R_SPARC_8:
+      *(char *) reloc_addr = value;
+      break;
+    case R_SPARC_16:
+      *(short *) reloc_addr = value;
+      break;
+    case R_SPARC_32:
+      *(unsigned int *) reloc_addr = value;
+      break;
+    case R_SPARC_DISP8:
+      *(char *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP16:
+      *(short *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_DISP32:
+      *(unsigned int *) reloc_addr = (value - (Elf64_Addr) reloc_addr);
+      break;
+    case R_SPARC_WDISP30:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xc0000000) |
+        (((value - (Elf64_Addr) reloc_addr) >> 2) & 0x3fffffff));
+      break;
 
-       /* MEDLOW code model relocs */
-       case R_SPARC_LO10:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & ~0x3ff) |
-            (value & 0x3ff));
-         break;
-       case R_SPARC_HI22:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & 0xffc00000) |
-            (value >> 10));
-         break;
-       case R_SPARC_OLO10:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & ~0x1fff) |
-            (((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));
-         break;
+      /* MEDLOW code model relocs */
+    case R_SPARC_LO10:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & ~0x3ff) |
+        (value & 0x3ff));
+      break;
+    case R_SPARC_HI22:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xffc00000) |
+        ((value >> 10) & 0x3fffff));
+      break;
+    case R_SPARC_OLO10:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & ~0x1fff) |
+        (((value & 0x3ff) + ELF64_R_TYPE_DATA (reloc->r_info)) & 0x1fff));
+      break;
 
-       /* MEDMID code model relocs */
-       case R_SPARC_H44:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & 0xffc00000) |
-            (value >> 22));
-         break;
-       case R_SPARC_M44:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & ~0x3ff) |
-            ((value >> 12) & 0x3ff));
-         break;
-       case R_SPARC_L44:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & ~0xfff) |
-            (value & 0xfff));
-         break;
+      /* ABS34 code model reloc */
+    case R_SPARC_H34:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xffc00000) |
+        ((value >> 12) & 0x3fffff));
+
+      /* MEDMID code model relocs */
+    case R_SPARC_H44:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xffc00000) |
+        ((value >> 22) & 0x3fffff));
+      break;
+    case R_SPARC_M44:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & ~0x3ff) |
+        ((value >> 12) & 0x3ff));
+      break;
+    case R_SPARC_L44:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & ~0xfff) |
+        (value & 0xfff));
+      break;
 
-       /* MEDANY code model relocs */
-       case R_SPARC_HH22:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & 0xffc00000) |
-            (value >> 42));
-         break;
-       case R_SPARC_HM10:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & ~0x3ff) |
-            ((value >> 32) & 0x3ff));
-         break;
-       case R_SPARC_LM22:
-         *(unsigned int *) reloc_addr =
-           ((*(unsigned int *)reloc_addr & 0xffc00000) |
-            ((value >> 10) & 0x003fffff));
-         break;
-#endif
-       case R_SPARC_JMP_SLOT:
-         elf_machine_fixup_plt(map, 0, reloc, reloc_addr, value);
-         break;
-#ifndef RTLD_BOOTSTRAP
-       case R_SPARC_UA64:
-         if (! ((long) reloc_addr & 3))
-           {
-             /* Common in .eh_frame */
-             ((unsigned int *) reloc_addr) [0] = value >> 32;
-             ((unsigned int *) reloc_addr) [1] = value;
-             break;
-           }
-         ((unsigned char *) reloc_addr) [0] = value >> 56;
-         ((unsigned char *) reloc_addr) [1] = value >> 48;
-         ((unsigned char *) reloc_addr) [2] = value >> 40;
-         ((unsigned char *) reloc_addr) [3] = value >> 32;
-         ((unsigned char *) reloc_addr) [4] = value >> 24;
-         ((unsigned char *) reloc_addr) [5] = value >> 16;
-         ((unsigned char *) reloc_addr) [6] = value >> 8;
-         ((unsigned char *) reloc_addr) [7] = value;
+      /* MEDANY code model relocs */
+    case R_SPARC_HH22:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xffc00000) |
+        (value >> 42));
+      break;
+    case R_SPARC_HM10:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & ~0x3ff) |
+        ((value >> 32) & 0x3ff));
+      break;
+    case R_SPARC_LM22:
+      *(unsigned int *) reloc_addr =
+       ((*(unsigned int *)reloc_addr & 0xffc00000) |
+        ((value >> 10) & 0x003fffff));
+      break;
+    case R_SPARC_UA16:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [1] = value;
+      break;
+    case R_SPARC_UA32:
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 24;
+      ((unsigned char *) reloc_addr_arg) [1] = value >> 16;
+      ((unsigned char *) reloc_addr_arg) [2] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [3] = value;
+      break;
+    case R_SPARC_UA64:
+      if (! ((long) reloc_addr_arg & 3))
+       {
+         /* Common in .eh_frame */
+         ((unsigned int *) reloc_addr_arg) [0] = value >> 32;
+         ((unsigned int *) reloc_addr_arg) [1] = value;
          break;
+       }
+      ((unsigned char *) reloc_addr_arg) [0] = value >> 56;
+      ((unsigned char *) reloc_addr_arg) [1] = value >> 48;
+      ((unsigned char *) reloc_addr_arg) [2] = value >> 40;
+      ((unsigned char *) reloc_addr_arg) [3] = value >> 32;
+      ((unsigned char *) reloc_addr_arg) [4] = value >> 24;
+      ((unsigned char *) reloc_addr_arg) [5] = value >> 16;
+      ((unsigned char *) reloc_addr_arg) [6] = value >> 8;
+      ((unsigned char *) reloc_addr_arg) [7] = value;
+      break;
 #endif
 #if !defined RTLD_BOOTSTRAP || defined _NDEBUG
-       default:
-         _dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 0);
-         break;
+    default:
+      _dl_reloc_bad_type (map, r_type, 0);
+      break;
 #endif
-       }
     }
 }
 
-static inline void
-elf_machine_lazy_rel (struct link_map *map,
-                     Elf64_Addr l_addr, const Elf64_Rela *reloc)
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
+                          void *const reloc_addr_arg)
 {
-  switch (ELF64_R_TYPE (reloc->r_info))
-    {
-    case R_SPARC_NONE:
-      break;
-    case R_SPARC_JMP_SLOT:
-      break;
-    default:
-      _dl_reloc_bad_type (map, ELFW(R_TYPE) (reloc->r_info), 1);
-      break;
-    }
+  Elf64_Addr *const reloc_addr = reloc_addr_arg;
+  *reloc_addr = l_addr + reloc->r_addend;
 }
 
-#endif /* RESOLVE */
-
-/* Nonzero iff TYPE should not be allowed to resolve to one of
-   the main executable's symbols, as for a COPY reloc.  */
-#define elf_machine_lookup_noexec_p(type) ((type) == R_SPARC_COPY)
-
-/* Nonzero iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.  */
-#define elf_machine_lookup_noplt_p(type) ((type) == R_SPARC_JMP_SLOT)
-
-/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
-#define ELF_MACHINE_JMP_SLOT   R_SPARC_JMP_SLOT
-
-/* The SPARC never uses Elf64_Rel relocations.  */
-#define ELF_MACHINE_NO_REL 1
-
-/* The SPARC overlaps DT_RELA and DT_PLTREL.  */
-#define ELF_MACHINE_PLTREL_OVERLAP 1
-
-/* Set up the loaded object described by L so its unrelocated PLT
-   entries will jump to the on-demand fixup code in dl-runtime.c.  */
-
-static inline int
-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
+auto inline void
+__attribute__ ((always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+                     Elf64_Addr l_addr, const Elf64_Rela *reloc,
+                     int skip_ifunc)
 {
-  if (l->l_info[DT_JMPREL] && lazy)
-    {
-      extern void _dl_runtime_resolve_0 (void);
-      extern void _dl_runtime_resolve_1 (void);
-      extern void _dl_runtime_profile_0 (void);
-      extern void _dl_runtime_profile_1 (void);
-      Elf64_Addr res0_addr, res1_addr;
-      unsigned int *plt = (void *) D_PTR (l, l_info[DT_PLTGOT]);
+  Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
+  const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
 
-      if (! profile)
+  if (__glibc_likely (r_type == R_SPARC_JMP_SLOT))
+    ;
+  else if (r_type == R_SPARC_JMP_IREL
+          || r_type == R_SPARC_IRELATIVE)
+    {
+      Elf64_Addr value = map->l_addr + reloc->r_addend;
+      if (__glibc_likely (!skip_ifunc))
+       value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
+      if (r_type == R_SPARC_JMP_IREL)
        {
-         res0_addr = (Elf64_Addr) &_dl_runtime_resolve_0;
-         res1_addr = (Elf64_Addr) &_dl_runtime_resolve_1;
+         /* 'high' is always zero, for large PLT entries the linker
+            emits an R_SPARC_IRELATIVE.  */
+         sparc64_fixup_plt (map, reloc, reloc_addr, value, 0, 1);
        }
       else
-       {
-         res0_addr = (Elf64_Addr) &_dl_runtime_profile_0;
-         res1_addr = (Elf64_Addr) &_dl_runtime_profile_1;
-         if (_dl_name_match_p (_dl_profile, l))
-           _dl_profile_map = l;
-       }
-
-      /* PLT0 looks like:
-
-        save   %sp, -192, %sp
-        sethi  %hh(_dl_runtime_{resolve,profile}_0), %l0
-        sethi  %lm(_dl_runtime_{resolve,profile}_0), %l1
-        or     %l0, %hm(_dl_runtime_{resolve,profile}_0), %l0
-        or     %l1, %lo(_dl_runtime_{resolve,profile}_0), %l1
-        sllx   %l0, 32, %l0
-        jmpl   %l0 + %l1, %l6
-         sethi %hi(0xffc00), %l2
-       */
-
-      plt[0] = 0x9de3bf40;
-      plt[1] = 0x21000000 | (res0_addr >> (64 - 22));
-      plt[2] = 0x23000000 | ((res0_addr >> 10) & 0x003fffff);
-      plt[3] = 0xa0142000 | ((res0_addr >> 32) & 0x3ff);
-      plt[4] = 0xa2146000 | (res0_addr & 0x3ff);
-      plt[5] = 0xa12c3020;
-      plt[6] = 0xadc40011;
-      plt[7] = 0x250003ff;
-
-      /* PLT1 looks like:
-
-        save   %sp, -192, %sp
-        sethi  %hh(_dl_runtime_{resolve,profile}_1), %l0
-        sethi  %lm(_dl_runtime_{resolve,profile}_1), %l1
-        or     %l0, %hm(_dl_runtime_{resolve,profile}_1), %l0
-        or     %l1, %lo(_dl_runtime_{resolve,profile}_1), %l1
-        sllx   %l0, 32, %l0
-        jmpl   %l0 + %l1, %l6
-         srlx  %g1, 12, %o1
-       */
-
-      plt[8 + 0] = 0x9de3bf40;
-      plt[8 + 1] = 0x21000000 | (res1_addr >> (64 - 22));
-      plt[8 + 2] = 0x23000000 | ((res1_addr >> 10) & 0x003fffff);
-      plt[8 + 3] = 0xa0142000 | ((res1_addr >> 32) & 0x3ff);
-      plt[8 + 4] = 0xa2146000 | (res1_addr & 0x3ff);
-      plt[8 + 5] = 0xa12c3020;
-      plt[8 + 6] = 0xadc40011;
-      plt[8 + 7] = 0x9330700c;
-
-      /* Now put the magic cookie at the beginning of .PLT2
-        Entry .PLT3 is unused by this implementation.  */
-      *((struct link_map **)(&plt[16 + 0])) = l;
+       *reloc_addr = value;
     }
-
-  return lazy;
+  else if (r_type == R_SPARC_NONE)
+    ;
+  else
+    _dl_reloc_bad_type (map, r_type, 1);
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name)    \
-  asm ("\
-       .text
-       .globl  " #tramp_name "_0
-       .type   " #tramp_name "_0, @function
-       .align  32
-" #tramp_name "_0:
-       ! sethi   %hi(1047552), %l2 - Done in .PLT0
-       ldx     [%l6 + 32 + 8], %o0
-       sub     %g1, %l6, %l0
-       xor     %l2, -1016, %l2
-       sethi   %hi(5120), %l3  ! 160 * 32
-       add     %l0, %l2, %l0
-       sethi   %hi(32768), %l4
-       udivx   %l0, %l3, %l3
-       sllx    %l3, 2, %l1
-       add     %l1, %l3, %l1
-       sllx    %l1, 10, %l2
-       sub     %l4, 4, %l4     ! No thanks to Sun for not obeying their own ABI
-       sllx    %l1, 5, %l1
-       sub     %l0, %l2, %l0
-       udivx   %l0, 24, %l0
-       add     %l0, %l4, %l0
-       add     %l1, %l0, %l1
-       add     %l1, %l1, %l0
-       add     %l0, %l1, %l0
-       mov     %i7, %o2
-       call    " #fixup_name "
-        sllx    %l0, 3, %o1
-       jmp     %o0
-        restore
-       .size   " #tramp_name "_0, . - " #tramp_name "_0
-
-       .globl  " #tramp_name "_1
-       .type   " #tramp_name "_1, @function
-       .align  32
-" #tramp_name "_1:
-       ! srlx  %g1, 12, %o1 - Done in .PLT1
-       ldx     [%l6 + 8], %o0
-       add     %o1, %o1, %o3
-       sub     %o1, 96, %o1    ! No thanks to Sun for not obeying their own ABI
-       mov     %i7, %o2
-       call    " #fixup_name "
-        add    %o1, %o3, %o1
-       jmp     %o0
-        restore
-       .size   " #tramp_name "_1, . - " #tramp_name "_1
-       .previous");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE                 \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);    \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE                 \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);    \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, fixup);
-#endif
-
-/* The PLT uses Elf64_Rela relocs.  */
-#define elf_machine_relplt elf_machine_rela
-
-/* Initial entry point code for the dynamic linker.
-   The C function `_dl_start' is the real entry point;
-   its return value is the user program's entry point.  */
-
-#define __S1(x)        #x
-#define __S(x) __S1(x)
-
-#define RTLD_START __asm__ ( "\
-       .text
-       .global _start
-       .type   _start, @function
-       .align  32
-_start:
-   /* Make room for functions to drop their arguments on the stack.  */
-       sub     %sp, 6*8, %sp
-   /* Pass pointer to argument block to _dl_start.  */
-       call    _dl_start
-        add     %sp," __S(STACK_BIAS) "+22*8,%o0
-       /* FALLTHRU */
-       .size _start, .-_start
-
-       .global _dl_start_user
-       .type   _dl_start_user, @function
-_dl_start_user:
-   /* Load the GOT register.  */
-1:     call    11f
-        sethi  %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7
-11:    or      %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7
-  /* Store the highest stack address.  */
-       sethi   %hi(__libc_stack_end), %g5
-       add     %l7, %o7, %l7
-       or      %g5, %lo(__libc_stack_end), %g5
-   /* Save the user entry point address in %l0.  */
-       mov     %o0, %l0
-       ldx     [%l7 + %g5], %l1
-       sethi   %hi(_dl_skip_args), %g5
-       add     %sp, 6*8, %l2
-   /* See if we were run as a command with the executable file name as an
-      extra leading argument.  If so, we must shift things around since we
-      must keep the stack doubleword aligned.  */
-       or      %g5, %lo(_dl_skip_args), %g5
-       stx     %l2, [%l1]
-       ldx     [%l7 + %g5], %i0
-       ld      [%i0], %i0
-       brz,pt  %i0, 2f
-        ldx    [%sp + " __S(STACK_BIAS) " + 22*8], %i5
-       /* Find out how far to shift.  */
-       sethi   %hi(_dl_argv), %l4
-       sub     %i5, %i0, %i5
-       or      %l4, %lo(_dl_argv), %l4
-       sllx    %i0, 3, %l6
-       ldx     [%l7 + %l4], %l4
-       stx     %i5, [%sp + " __S(STACK_BIAS) " + 22*8]
-       add     %sp, " __S(STACK_BIAS) " + 23*8, %i1
-       add     %i1, %l6, %i2
-       ldx     [%l4], %l5
-       /* Copy down argv.  */
-12:    ldx     [%i2], %i3
-       add     %i2, 8, %i2
-       stx     %i3, [%i1]
-       brnz,pt %i3, 12b
-        add    %i1, 8, %i1
-       sub     %l5, %l6, %l5
-       /* Copy down envp.  */
-13:    ldx     [%i2], %i3
-       add     %i2, 8, %i2
-       stx     %i3, [%i1]
-       brnz,pt %i3, 13b
-        add    %i1, 8, %i1
-       /* Copy down auxiliary table.  */
-14:    ldx     [%i2], %i3
-       ldx     [%i2 + 8], %i4
-       add     %i2, 16, %i2
-       stx     %i3, [%i1]
-       stx     %i4, [%i1 + 8]
-       brnz,pt %i3, 14b
-        add    %i1, 16, %i1
-       stx     %l5, [%l4]
-  /* %o0 = _dl_loaded, %o1 = argc, %o2 = argv, %o3 = envp.  */
-2:     sethi   %hi(_dl_loaded), %o0
-       add     %sp, " __S(STACK_BIAS) " + 23*8, %o2
-       orcc    %o0, %lo(_dl_loaded), %o0
-       sllx    %i5, 3, %o3
-       ldx     [%l7 + %o0], %o0
-       add     %o3, 8, %o3
-       mov     %i5, %o1
-       add     %o2, %o3, %o3
-       call    _dl_init
-        ldx    [%o0], %o0
-   /* Pass our finalizer function to the user in %g1.  */
-       sethi   %hi(_dl_fini), %g1
-       or      %g1, %lo(_dl_fini), %g1
-       ldx     [%l7 + %g1], %g1
-  /* Jump to the user's entry point and deallocate the extra stack we got.  */
-       jmp     %l0
-        add    %sp, 6*8, %sp
-       .size   _dl_start_user, . - _dl_start_user
-       .previous");
+#endif /* RESOLVE_MAP */