]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/m68k/dl-machine.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / m68k / dl-machine.h
index b8911dccc7c6ec80db74b18b8f6861727e2472f8..2a8b3cdd04caad149563c215f82a8699e2126094 100644 (file)
@@ -1,21 +1,20 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  m68k version.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996-2019 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 "m68k"
 
 #include <sys/param.h>
+#include <sysdep.h>
+#include <dl-tls.h>
 
-#include <assert.h>
-
-/* Return nonzero iff E_MACHINE is compatible with the running host.  */
+/* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int
-elf_machine_matches_host (Elf32_Half e_machine)
+elf_machine_matches_host (const Elf32_Ehdr *ehdr)
 {
-  switch (e_machine)
-    {
-    case EM_68K:
-      return 1;
-    default:
-      return 0;
-    }
+  return ehdr->e_machine == EM_68K;
 }
 
 
-/* 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.  */
+/* Return the link-time address of _DYNAMIC.
+   This must be inlined in a function which uses global data.  */
 static inline Elf32_Addr
 elf_machine_dynamic (void)
 {
-  register Elf32_Addr *got asm ("%a5");
-  return *got;
+  Elf32_Addr addr;
+
+  asm ("move.l _DYNAMIC@GOT.w(%%a5), %0"
+       : "=a" (addr));
+  return addr;
 }
 
 
@@ -56,9 +51,15 @@ static inline Elf32_Addr
 elf_machine_load_address (void)
 {
   Elf32_Addr addr;
-  asm ("lea _dl_start(%%pc), %0\n\t"
+#ifdef SHARED
+  asm (PCREL_OP ("lea", "_dl_start", "%0", "%0", "%%pc") "\n\t"
        "sub.l _dl_start@GOT.w(%%a5), %0"
        : "=a" (addr));
+#else
+  asm (PCREL_OP ("lea", "_dl_relocate_static_pie", "%0", "%0", "%%pc") "\n\t"
+       "sub.l _dl_relocate_static_pie@GOT.w(%%a5), %0"
+       : "=a" (addr));
+#endif
   return addr;
 }
 
@@ -66,7 +67,7 @@ elf_machine_load_address (void)
 /* 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
+static inline int __attribute__ ((always_inline))
 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 {
   Elf32_Addr *got;
@@ -80,7 +81,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
         to push an offset into the .rela.plt section, push
         _GLOBAL_OFFSET_TABLE_[1], and then jump to
         _GLOBAL_OFFSET_TABLE_[2].  */
-      got = (Elf32_Addr *) (l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr);
+      got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
       got[1] = (Elf32_Addr) l; /* Identify this shared object.  */
 
       /* The got[2] entry contains the address of a function which gets
@@ -93,11 +94,12 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
        {
          got[2] = (Elf32_Addr) &_dl_runtime_profile;
 
-         if (_dl_name_match_p (_dl_profile, l))
+         if (GLRO(dl_profile) != NULL
+             && _dl_name_match_p (GLRO(dl_profile), l))
            {
              /* This is the object we are looking for.  Say that we really
                 want profiling and the timers are started.  */
-             _dl_profile_map = l;
+             GL(dl_profile_map) = l;
            }
        }
       else
@@ -109,37 +111,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* 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) \
-"| Trampoline for " #fixup_name "
-       .globl " #tramp_name "
-       .type " #tramp_name ", @function
-" #tramp_name ":
-       | Save %a0 (struct return address) and %a1.
-       move.l %a0, -(%sp)
-       move.l %a1, -(%sp)
-       | Call the real address resolver.
-       jbsr " #fixup_name "
-       | Restore register %a0 and %a1.
-       move.l (%sp)+, %a1
-       move.l (%sp)+, %a0
-       | Pop parameters
-       addq.l #8, %sp
-       | Call real function.
-       jmp (%d0)
-       .size " #tramp_name ", . - " #tramp_name "\n"
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
-     TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup));
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
-     ".globl _dl_runtime_profile\n" \
-     ".set _dl_runtime_profile, _dl_runtime_resolve");
-#endif
 #define ELF_MACHINE_RUNTIME_FIXUP_ARGS long int save_a0, long int save_a1
+#define ELF_MACHINE_RUNTIME_FIXUP_PARAMS save_a0, save_a1
 
 
 /* Mask identifying addresses reserved for the user program,
@@ -151,86 +124,75 @@ asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
    its return value is the user program's entry point.  */
 
 #define RTLD_START asm ("\
-       .text
-       .globl _start
-       .type _start,@function
-_start:
-       move.l %sp, -(%sp)
-       jbsr _dl_start
-       addq.l #4, %sp
-
-       .globl _dl_start_user
-       .type _dl_start_user,@function
-_dl_start_user:
-       | Save the user entry point address in %a4.
-       move.l %d0, %a4
-       | Point %a5 at the GOT.
-       lea _GLOBAL_OFFSET_TABLE_@GOTPC(%pc), %a5
-       | Remember the highest stack address.
-       move.l %sp, ([__libc_stack_end@GOT.w, %a5])
-       | See if we were run as a command with the executable file
-       | name as an extra leading argument.
-       move.l ([_dl_skip_args@GOT.w, %a5]), %d0
-       jeq 0f
-       | Pop the original argument count
-       move.l (%sp)+, %d1
-       | Subtract _dl_skip_args from it.
-       sub.l %d0, %d1
-       | Adjust the stack pointer to skip _dl_skip_args words.
-       lea (%sp, %d0*4), %sp
-       | Push back the modified argument count.
-       move.l %d1, -(%sp)
-0:     | Push _dl_default_scope[2] as argument in _dl_init_next call below.
-       move.l ([_dl_default_scope@GOT.w, %a5], 8), %d2
-0:     move.l %d2, -(%sp)
-       | Call _dl_init_next to return the address of an initializer
-       | function to run.
-       bsr.l _dl_init_next@PLTPC
-       add.l #4, %sp | Pop argument.
-       | Check for zero return, when out of initializers.
-       tst.l %d0
-       jeq 1f
-       | Call the shared object initializer function.
-       | NOTE: We depend only on the registers (%d2, %a4 and %a5)
-       | and the return address pushed by this call;
-       | the initializer is called with the stack just
-       | as it appears on entry, and it is free to move
-       | the stack around, as long as it winds up jumping to
-       | the return address on the top of the stack.
-       move.l %d0, %a0
-       jsr (%a0)
-       | Loop to call _dl_init_next for the next initializer.
-       jra 0b
-1:     | Clear the startup flag.
-       clr.l _dl_starting_up@GOT.w(%a5)
-       | Pass our finalizer function to the user in %a1.
-       move.l _dl_fini@GOT.w(%a5), %a1
-       | Initialize %fp with the stack pointer.
-       move.l %sp, %fp
-       | Jump to the user's entry point.
-       jmp (%a4)
-       .size _dl_start_user, . - _dl_start_user
+       .text\n\
+       .globl _start\n\
+       .type _start,@function\n\
+_start:\n\
+       sub.l %fp, %fp\n\
+       move.l %sp, -(%sp)\n\
+       jbsr _dl_start\n\
+       addq.l #4, %sp\n\
+       /* FALLTHRU */\n\
+\n\
+       .globl _dl_start_user\n\
+       .type _dl_start_user,@function\n\
+_dl_start_user:\n\
+       | Save the user entry point address in %a4.\n\
+       move.l %d0, %a4\n\
+       | See if we were run as a command with the executable file\n\
+       | name as an extra leading argument.\n\
+       " PCREL_OP ("move.l", "_dl_skip_args", "%d0", "%d0", "%pc") "\n\
+       | Pop the original argument count\n\
+       move.l (%sp)+, %d1\n\
+       | Subtract _dl_skip_args from it.\n\
+       sub.l %d0, %d1\n\
+       | Adjust the stack pointer to skip _dl_skip_args words.\n\
+       lea (%sp, %d0*4), %sp\n\
+       | Push back the modified argument count.\n\
+       move.l %d1, -(%sp)\n\
+       # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
+       pea 8(%sp, %d1*4)\n\
+       pea 8(%sp)\n\
+       move.l %d1, -(%sp)\n\
+       " PCREL_OP ("move.l", "_rtld_local", "-(%sp)", "%d0", "%pc") "\n\
+       jbsr _dl_init\n\
+       addq.l #8, %sp\n\
+       addq.l #8, %sp\n\
+       | Pass our finalizer function to the user in %a1.\n\
+       " PCREL_OP ("lea", "_dl_fini", "%a1", "%a1", "%pc") "\n\
+       | Initialize %fp with the stack pointer.\n\
+       move.l %sp, %fp\n\
+       | Jump to the user's entry point.\n\
+       jmp (%a4)\n\
+       .size _dl_start_user, . - _dl_start_user\n\
        .previous");
 
-/* Nonzero iff TYPE describes a relocation that should
-   skip the executable when looking up the symbol value.  */
-#define elf_machine_lookup_noexec_p(type) ((type) == R_68K_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_68K_JMP_SLOT)
+/* 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_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_68K_JMP_SLOT       \
+     || (type) == R_68K_TLS_DTPMOD32 \
+     || (type) == R_68K_TLS_DTPREL32 \
+     || (type) == R_68K_TLS_TPREL32) * ELF_RTYPE_CLASS_PLT)    \
+   | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT   R_68K_JMP_SLOT
 
 /* The m68k never uses Elf32_Rel relocations.  */
 #define ELF_MACHINE_NO_REL 1
+#define ELF_MACHINE_NO_RELA 0
 
-static inline void
-elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
+static inline Elf32_Addr
+elf_machine_fixup_plt (struct link_map *map, lookup_t t,
+                      const ElfW(Sym) *refsym, const ElfW(Sym) *sym,
+                      const Elf32_Rela *reloc,
                       Elf32_Addr *reloc_addr, Elf32_Addr value)
 {
-  *reloc_addr = value;
+  return *reloc_addr = value;
 }
 
 /* Return the final value of a plt relocation.  On the m68k the JMP_SLOT
@@ -242,28 +204,34 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
   return value;
 }
 
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER m68k_gnu_pltenter
+#define ARCH_LA_PLTEXIT m68k_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#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__ ((unused, always_inline))
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
                  const Elf32_Sym *sym, const struct r_found_version *version,
-                 Elf32_Addr *const reloc_addr)
+                 void *const reloc_addr_arg, int skip_ifunc)
 {
-  if (ELF32_R_TYPE (reloc->r_info) == R_68K_RELATIVE)
+  Elf32_Addr *const reloc_addr = reloc_addr_arg;
+  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+
+  if (__builtin_expect (r_type == R_68K_RELATIVE, 0))
     *reloc_addr = map->l_addr + reloc->r_addend;
   else
     {
       const Elf32_Sym *const refsym = sym;
-      Elf32_Addr value = RESOLVE (&sym, version, ELF32_R_TYPE (reloc->r_info));
-      if (sym)
-       value += sym->st_value;
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true);
 
-      switch (ELF32_R_TYPE (reloc->r_info))
+      switch (r_type)
        {
        case R_68K_COPY:
          if (sym == NULL)
@@ -271,20 +239,17 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
               found.  */
            break;
          if (sym->st_size > refsym->st_size
-             || (_dl_verbose && sym->st_size < refsym->st_size))
+             || (sym->st_size < refsym->st_size && GLRO(dl_verbose)))
            {
-             extern char **_dl_argv;
              const char *strtab;
 
-             strtab = ((void *) map->l_addr
-                       + map->l_info[DT_STRTAB]->d_un.d_ptr);
-             _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>",
-                               ": Symbol `", strtab + refsym->st_name,
-                               "' has different size in shared object, "
-                               "consider re-linking\n", NULL);
+             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",
+                               RTLD_PROGNAME, strtab + refsym->st_name);
            }
-         memcpy (reloc_addr, (void *) value, MIN (sym->st_size,
-                                                  refsym->st_size));
+         memcpy (reloc_addr_arg, (void *) value,
+                 MIN (sym->st_size, refsym->st_size));
          break;
        case R_68K_GLOB_DAT:
        case R_68K_JMP_SLOT:
@@ -310,28 +275,52 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
        case R_68K_PC32:
          *reloc_addr = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
          break;
+#ifndef RTLD_BOOTSTRAP
+       case R_68K_TLS_DTPMOD32:
+         /* 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_68K_TLS_DTPREL32:
+         if (sym != NULL)
+           *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
+         break;
+       case R_68K_TLS_TPREL32:
+         if (sym != NULL)
+           {
+             CHECK_STATIC_TLS (map, sym_map);
+             *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
+           }
+         break;
+#endif /* !RTLD_BOOTSTRAP */
        case R_68K_NONE:                /* Alright, Wilbur.  */
          break;
        default:
-         assert (! "unexpected dynamic reloc type");
+         _dl_reloc_bad_type (map, r_type, 0);
          break;
        }
     }
 }
 
-static inline void
-elf_machine_lazy_rel (Elf32_Addr l_addr, const Elf32_Rela *reloc)
+auto inline void __attribute__ ((unused, always_inline))
+elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
+                          void *const reloc_addr_arg)
+{
+  Elf32_Addr *const reloc_addr = reloc_addr_arg;
+  *reloc_addr = l_addr + reloc->r_addend;
+}
+
+auto inline void __attribute__ ((unused, always_inline))
+elf_machine_lazy_rel (struct link_map *map,
+                     Elf32_Addr l_addr, const Elf32_Rela *reloc,
+                     int skip_ifunc)
 {
   Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
-  switch (ELF32_R_TYPE (reloc->r_info))
-    {
-    case R_68K_JMP_SLOT:
-      *reloc_addr += l_addr;
-      break;
-    default:
-      assert (! "unexpected PLT reloc type");
-      break;
-    }
+  if (ELF32_R_TYPE (reloc->r_info) == R_68K_JMP_SLOT)
+    *reloc_addr += l_addr;
+  else
+    _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */