abe59f
commit 8dbb7a08ec52057819db4ee234f9429ab99eb4ae
abe59f
Author: Vineet Gupta <vgupta@synopsys.com>
abe59f
Date:   Wed May 27 12:54:21 2020 -0700
abe59f
abe59f
    dl-runtime: reloc_{offset,index} now functions arch overide'able
abe59f
    
abe59f
    The existing macros are fragile and expect local variables with a
abe59f
    certain name. Fix this by defining them as functions with default
abe59f
    implementation in a new header dl-runtime.h which arches can override
abe59f
    if need be.
abe59f
    
abe59f
    This came up during ARC port review, hence the need for argument pltgot
abe59f
    in reloc_index() which is not needed by existing ports.
abe59f
    
abe59f
    This patch potentially only affects hppa/x86 ports,
abe59f
    build tested for both those configs and a few more.
abe59f
    
abe59f
    Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
abe59f
abe59f
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
abe59f
index 72b03e000dcf190e..4ccd7c30678fafad 100644
abe59f
--- a/elf/dl-runtime.c
abe59f
+++ b/elf/dl-runtime.c
abe59f
@@ -27,6 +27,7 @@
abe59f
 #include "dynamic-link.h"
abe59f
 #include <tls.h>
abe59f
 #include <dl-irel.h>
abe59f
+#include <dl-runtime.h>
abe59f
 
abe59f
 
abe59f
 #if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
abe59f
@@ -42,13 +43,6 @@
abe59f
 # define ARCH_FIXUP_ATTRIBUTE
abe59f
 #endif
abe59f
 
abe59f
-#ifndef reloc_offset
abe59f
-# define reloc_offset reloc_arg
abe59f
-# define reloc_index  reloc_arg / sizeof (PLTREL)
abe59f
-#endif
abe59f
-
abe59f
-
abe59f
-
abe59f
 /* This function is called through a special trampoline from the PLT the
abe59f
    first time each PLT entry is called.  We must perform the relocation
abe59f
    specified in the PLT of the given shared object, and return the resolved
abe59f
@@ -68,8 +62,11 @@ _dl_fixup (
abe59f
     = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
abe59f
   const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
abe59f
 
abe59f
+  const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
abe59f
+
abe59f
   const PLTREL *const reloc
abe59f
-    = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
abe59f
+    = (const void *) (D_PTR (l, l_info[DT_JMPREL])
abe59f
+		      + reloc_offset (pltgot, reloc_arg));
abe59f
   const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
abe59f
   const ElfW(Sym) *refsym = sym;
abe59f
   void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
abe59f
@@ -180,9 +177,12 @@ _dl_profile_fixup (
abe59f
 			l, reloc_arg);
abe59f
     }
abe59f
 
abe59f
+  const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
abe59f
+
abe59f
   /* This is the address in the array where we store the result of previous
abe59f
      relocations.  */
abe59f
-  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
abe59f
+  struct reloc_result *reloc_result
abe59f
+    = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
abe59f
 
abe59f
  /* CONCURRENCY NOTES:
abe59f
 
abe59f
@@ -219,8 +219,11 @@ _dl_profile_fixup (
abe59f
 	= (const void *) D_PTR (l, l_info[DT_SYMTAB]);
abe59f
       const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]);
abe59f
 
abe59f
+      const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
abe59f
+
abe59f
       const PLTREL *const reloc
abe59f
-	= (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
abe59f
+	= (const void *) (D_PTR (l, l_info[DT_JMPREL])
abe59f
+			  + reloc_offset (pltgot, reloc_arg));
abe59f
       const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)];
abe59f
       const ElfW(Sym) *defsym = refsym;
abe59f
       lookup_t result;
abe59f
@@ -485,11 +488,14 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
abe59f
 		  const void *inregs, void *outregs)
abe59f
 {
abe59f
 #ifdef SHARED
abe59f
+  const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
abe59f
+
abe59f
   /* This is the address in the array where we store the result of previous
abe59f
      relocations.  */
abe59f
   // XXX Maybe the bound information must be stored on the stack since
abe59f
   // XXX with bind_not a new value could have been stored in the meantime.
abe59f
-  struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
abe59f
+  struct reloc_result *reloc_result =
abe59f
+    &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
abe59f
   ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
abe59f
 					    l_info[DT_SYMTAB])
abe59f
 		       + reloc_result->boundndx);
abe59f
diff --git a/elf/dl-runtime.h b/elf/dl-runtime.h
abe59f
new file mode 100644
abe59f
index 0000000000000000..78f1da77fb4ed905
abe59f
--- /dev/null
abe59f
+++ b/elf/dl-runtime.h
abe59f
@@ -0,0 +1,30 @@
abe59f
+/* Helpers for On-demand PLT fixup for shared objects.  Generic version.
abe59f
+   Copyright (C) 2020 Free Software Foundation, Inc.
abe59f
+   This file is part of the GNU C Library.
abe59f
+
abe59f
+   The GNU C Library is free software; you can redistribute it and/or
abe59f
+   modify it under the terms of the GNU Lesser General Public
abe59f
+   License as published by the Free Software Foundation; either
abe59f
+   version 2.1 of the License, or (at your option) any later version.
abe59f
+
abe59f
+   The GNU C Library is distributed in the hope that it will be useful,
abe59f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
abe59f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
abe59f
+   Lesser General Public License for more details.
abe59f
+
abe59f
+   You should have received a copy of the GNU Lesser General Public
abe59f
+   License along with the GNU C Library; if not, write to the Free
abe59f
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
abe59f
+   02111-1307 USA.  */
abe59f
+
abe59f
+static inline uintptr_t
abe59f
+reloc_offset (uintptr_t plt0, uintptr_t pltn)
abe59f
+{
abe59f
+  return pltn;
abe59f
+}
abe59f
+
abe59f
+static inline uintptr_t
abe59f
+reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
abe59f
+{
abe59f
+  return pltn / size;
abe59f
+}
abe59f
diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c
abe59f
index 885a3f1837cbc56d..2d061b150f0602c1 100644
abe59f
--- a/sysdeps/hppa/dl-runtime.c
abe59f
+++ b/sysdeps/hppa/dl-runtime.c
abe59f
@@ -17,10 +17,6 @@
abe59f
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
abe59f
    02111-1307 USA.  */
abe59f
 
abe59f
-/* Clear PA_GP_RELOC bit in relocation offset.  */
abe59f
-#define reloc_offset (reloc_arg & ~PA_GP_RELOC)
abe59f
-#define reloc_index  (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL)
abe59f
-
abe59f
 #include <elf/dl-runtime.c>
abe59f
 
abe59f
 /* The caller has encountered a partially relocated function descriptor.
abe59f
diff --git a/sysdeps/hppa/dl-runtime.h b/sysdeps/hppa/dl-runtime.h
abe59f
new file mode 100644
abe59f
index 0000000000000000..6983aa0ae9b4296c
abe59f
--- /dev/null
abe59f
+++ b/sysdeps/hppa/dl-runtime.h
abe59f
@@ -0,0 +1,31 @@
abe59f
+/* Helpers for On-demand PLT fixup for shared objects.  HPAA version.
abe59f
+   Copyright (C) 2020 Free Software Foundation, Inc.
abe59f
+   This file is part of the GNU C Library.
abe59f
+
abe59f
+   The GNU C Library is free software; you can redistribute it and/or
abe59f
+   modify it under the terms of the GNU Lesser General Public
abe59f
+   License as published by the Free Software Foundation; either
abe59f
+   version 2.1 of the License, or (at your option) any later version.
abe59f
+
abe59f
+   The GNU C Library is distributed in the hope that it will be useful,
abe59f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
abe59f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
abe59f
+   Lesser General Public License for more details.
abe59f
+
abe59f
+   You should have received a copy of the GNU Lesser General Public
abe59f
+   License along with the GNU C Library; if not, write to the Free
abe59f
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
abe59f
+   02111-1307 USA.  */
abe59f
+
abe59f
+/* Clear PA_GP_RELOC bit in relocation offset.  */
abe59f
+static inline uintptr_t
abe59f
+reloc_offset (uintptr_t plt0, uintptr_t pltn)
abe59f
+{
abe59f
+  return pltn & ~PA_GP_RELOC;
abe59f
+}
abe59f
+
abe59f
+static inline uintptr_t
abe59f
+reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
abe59f
+{
abe59f
+  return (pltn & ~PA_GP_RELOC )/ size;
abe59f
+}
abe59f
diff --git a/sysdeps/x86_64/dl-runtime.c b/sysdeps/x86_64/dl-runtime.c
abe59f
deleted file mode 100644
abe59f
index b625d1e88257b018..0000000000000000
abe59f
--- a/sysdeps/x86_64/dl-runtime.c
abe59f
+++ /dev/null
abe59f
@@ -1,9 +0,0 @@
abe59f
-/* The ABI calls for the PLT stubs to pass the index of the relocation
abe59f
-   and not its offset.  In _dl_profile_fixup and _dl_call_pltexit we
abe59f
-   also use the index.  Therefore it is wasteful to compute the offset
abe59f
-   in the trampoline just to reverse the operation immediately
abe59f
-   afterwards.  */
abe59f
-#define reloc_offset reloc_arg * sizeof (PLTREL)
abe59f
-#define reloc_index  reloc_arg
abe59f
-
abe59f
-#include <elf/dl-runtime.c>
abe59f
diff --git a/sysdeps/x86_64/dl-runtime.h b/sysdeps/x86_64/dl-runtime.h
abe59f
new file mode 100644
abe59f
index 0000000000000000..3fa61d7a4697cf3f
abe59f
--- /dev/null
abe59f
+++ b/sysdeps/x86_64/dl-runtime.h
abe59f
@@ -0,0 +1,35 @@
abe59f
+/* Helpers for On-demand PLT fixup for shared objects.  x86_64 version.
abe59f
+   Copyright (C) 2020 Free Software Foundation, Inc.
abe59f
+   This file is part of the GNU C Library.
abe59f
+
abe59f
+   The GNU C Library is free software; you can redistribute it and/or
abe59f
+   modify it under the terms of the GNU Lesser General Public
abe59f
+   License as published by the Free Software Foundation; either
abe59f
+   version 2.1 of the License, or (at your option) any later version.
abe59f
+
abe59f
+   The GNU C Library is distributed in the hope that it will be useful,
abe59f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
abe59f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
abe59f
+   Lesser General Public License for more details.
abe59f
+
abe59f
+   You should have received a copy of the GNU Lesser General Public
abe59f
+   License along with the GNU C Library; if not, write to the Free
abe59f
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
abe59f
+   02111-1307 USA.  */
abe59f
+
abe59f
+/* The ABI calls for the PLT stubs to pass the index of the relocation
abe59f
+   and not its offset.  In _dl_profile_fixup and _dl_call_pltexit we
abe59f
+   also use the index.  Therefore it is wasteful to compute the offset
abe59f
+   in the trampoline just to reverse the operation immediately
abe59f
+   afterwards.  */
abe59f
+static inline uintptr_t
abe59f
+reloc_offset (uintptr_t plt0, uintptr_t pltn)
abe59f
+{
abe59f
+  return pltn * sizeof (ElfW(Rela));
abe59f
+}
abe59f
+
abe59f
+static inline uintptr_t
abe59f
+reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size)
abe59f
+{
abe59f
+  return pltn;
abe59f
+}