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