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