]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/s390/s390-64/dl-machine.h
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / s390 / s390-64 / dl-machine.h
index 067336e2a6909db1839f4aa0fa6aa406044ba0bb..c17c5c892afe82f5d97698ef4244eb02417c89d7 100644 (file)
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.
    64 bit S/390 Version.
-   Copyright (C) 2001-2012 Free Software Foundation, Inc.
+   Copyright (C) 2001-2019 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
@@ -16,7 +16,7 @@
 
    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/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
 #ifndef dl_machine_h
 #define dl_machine_h
@@ -26,6 +26,7 @@
 #include <sys/param.h>
 #include <string.h>
 #include <link.h>
+#include <sysdeps/s390/dl-procinfo.h>
 #include <dl-irel.h>
 
 #define ELF_MACHINE_IRELATIVE       R_390_IRELATIVE
@@ -50,8 +51,8 @@ elf_machine_dynamic (void)
 {
   register Elf64_Addr *got;
 
-  asm( "       larl   %0,_GLOBAL_OFFSET_TABLE_\n"
-       : "=&a" (got) : : "0" );
+  __asm__ ( "  larl   %0,_GLOBAL_OFFSET_TABLE_\n"
+           : "=&a" (got) : : "0" );
 
   return *got;
 }
@@ -62,11 +63,11 @@ elf_machine_load_address (void)
 {
   Elf64_Addr addr;
 
-  asm( "   larl         %0,_dl_start\n"
-       "   larl         1,_GLOBAL_OFFSET_TABLE_\n"
-       "   lghi         2,_dl_start@GOT\n"
-       "   slg  %0,0(2,1)"
-       : "=&d" (addr) : : "1", "2" );
+  __asm__( "   larl     %0,_dl_start\n"
+          "   larl      1,_GLOBAL_OFFSET_TABLE_\n"
+          "   lghi      2,_dl_start@GOT\n"
+          "   slg       %0,0(2,1)"
+          : "=&d" (addr) : : "1", "2" );
   return addr;
 }
 
@@ -78,6 +79,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   extern void _dl_runtime_resolve (Elf64_Word);
   extern void _dl_runtime_profile (Elf64_Word);
+#if defined HAVE_S390_VX_ASM_SUPPORT
+  extern void _dl_runtime_resolve_vx (Elf64_Word);
+  extern void _dl_runtime_profile_vx (Elf64_Word);
+#endif
 
   if (l->l_info[DT_JMPREL] && lazy)
     {
@@ -93,7 +98,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
       if (got[1])
        {
          l->l_mach.plt = got[1] + l->l_addr;
-         l->l_mach.gotplt = (Elf64_Addr) &got[3];
+         l->l_mach.jmprel = (const Elf64_Rela *) D_PTR (l, l_info[DT_JMPREL]);
        }
       got[1] = (Elf64_Addr) l; /* Identify this shared object.  */
 
@@ -103,9 +108,16 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
         to intercept the calls to collect information.  In this case we
         don't store the address in the GOT so that all future calls also
         end in this function.  */
-      if (__builtin_expect (profile, 0))
+      if (__glibc_unlikely (profile))
        {
+#if defined HAVE_S390_VX_ASM_SUPPORT
+         if (GLRO(dl_hwcap) & HWCAP_S390_VX)
+           got[2] = (Elf64_Addr) &_dl_runtime_profile_vx;
+         else
+           got[2] = (Elf64_Addr) &_dl_runtime_profile;
+#else
          got[2] = (Elf64_Addr) &_dl_runtime_profile;
+#endif
 
          if (GLRO(dl_profile) != NULL
              && _dl_name_match_p (GLRO(dl_profile), l))
@@ -114,9 +126,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
            GL(dl_profile_map) = l;
        }
       else
-       /* This function will get called to fix up the GOT entry indicated by
-          the offset on the stack, and then jump to the resolved address.  */
-       got[2] = (Elf64_Addr) &_dl_runtime_resolve;
+       {
+         /* This function will get called to fix up the GOT entry indicated by
+            the offset on the stack, and then jump to the resolved address.  */
+#if defined HAVE_S390_VX_ASM_SUPPORT
+         if (GLRO(dl_hwcap) & HWCAP_S390_VX)
+           got[2] = (Elf64_Addr) &_dl_runtime_resolve_vx;
+         else
+           got[2] = (Elf64_Addr) &_dl_runtime_resolve;
+#else
+         got[2] = (Elf64_Addr) &_dl_runtime_resolve;
+#endif
+       }
     }
 
   return lazy;
@@ -126,7 +147,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point. */
 
-#define RTLD_START asm ("\n\
+#define RTLD_START __asm__ ("\n\
 .text\n\
 .align 4\n\
 .globl _start\n\
@@ -175,7 +196,7 @@ _dl_start_user:\n\
        lgr   %r5,%r3\n\
        sllg  %r5,%r5,3\n\
        la    %r5,176(%r5,%r15)\n\
-       brasl %r14,_dl_init_internal@PLT\n\
+       brasl %r14,_dl_init@PLT\n\
        # Pass our finalizer function to the user in %r14, as per ELF ABI.\n\
        lghi  %r14,_dl_fini@GOT\n\
        lg    %r14,0(%r14,%r12)\n\
@@ -192,7 +213,7 @@ _dl_start_user:\n\
 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
    TLS variable, so undefined references should not be allowed to
    define the value.
-   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   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_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD                  \
@@ -205,6 +226,7 @@ _dl_start_user:\n\
 
 /* The 64 bit S/390 never uses Elf64_Rel relocations.  */
 #define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
 
 /* We define an initialization functions.  This is called very early in
    _dl_sysdep_start.  */
@@ -220,6 +242,7 @@ dl_platform_init (void)
 
 static inline Elf64_Addr
 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+                      const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
                       const Elf64_Rela *reloc,
                       Elf64_Addr *reloc_addr, Elf64_Addr value)
 {
@@ -255,7 +278,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
   const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
 
 #if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
-  if (__builtin_expect (r_type == R_390_RELATIVE, 0))
+  if (__glibc_unlikely (r_type == R_390_RELATIVE))
     {
 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
       /* This is defined in rtld.c, but nowhere in the static libc.a;
@@ -273,15 +296,16 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
     }
   else
 #endif
-  if (__builtin_expect (r_type == R_390_NONE, 0))
+  if (__glibc_unlikely (r_type == R_390_NONE))
     return;
   else
     {
-#ifndef RESOLVE_CONFLICT_FIND_MAP
+#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
+      /* Only needed for R_390_COPY below.  */
       const Elf64_Sym *const refsym = sym;
 #endif
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
-      Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+      Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
 
       if (sym != NULL
          && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
@@ -294,7 +318,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
        {
        case R_390_IRELATIVE:
          value = map->l_addr + reloc->r_addend;
-         if (__builtin_expect (!skip_ifunc, 1))
+         if (__glibc_likely (!skip_ifunc))
            value = elf_ifunc_invoke (value);
          *reloc_addr = value;
          break;
@@ -361,8 +385,7 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
              strtab = (const char *) D_PTR (map,l_info[DT_STRTAB]);
              _dl_error_printf ("\
 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
-                               rtld_progname ?: "<program name unknown>",
-                               strtab + refsym->st_name);
+                               RTLD_PROGNAME, strtab + refsym->st_name);
            }
          memcpy (reloc_addr_arg, (void *) value,
                  MIN (sym->st_size, refsym->st_size));
@@ -433,19 +456,17 @@ elf_machine_lazy_rel (struct link_map *map,
   Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
   const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
   /* Check for unexpected PLT reloc type.  */
-  if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
+  if (__glibc_likely (r_type == R_390_JMP_SLOT))
     {
       if (__builtin_expect (map->l_mach.plt, 0) == 0)
        *reloc_addr += l_addr;
       else
-       *reloc_addr =
-         map->l_mach.plt
-         + (((Elf64_Addr) reloc_addr) - map->l_mach.gotplt) * 4;
+       *reloc_addr = map->l_mach.plt + (reloc - map->l_mach.jmprel) * 32;
     }
-  else if (__builtin_expect (r_type == R_390_IRELATIVE, 1))
+  else if (__glibc_likely (r_type == R_390_IRELATIVE))
     {
       Elf64_Addr value = map->l_addr + reloc->r_addend;
-      if (__builtin_expect (!skip_ifunc, 1))
+      if (__glibc_likely (!skip_ifunc))
        value = elf_ifunc_invoke (value);
       *reloc_addr = value;
     }