This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] New sparc* elf_machine_load_address


Hi!

I'm going to commit a change into binutils to cope with a new "feature" in
Solaris ld.so and it breaks sparc-linux elf_machine_load_address
unfortunately. The following method is maybe not the fastest around
(2 additional reads), but certainly reliable and without need to rely on
stuff like relative position between .got and .dynamic or that that ld.so
is smaller than 1MB and aligned to 1MB (the last is not true for sparc32).

2002-09-24  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/sparc/sparc32/dl-machine.h (elf_machine_load_address): Don't
	rely on *r_offset of R_SPARC_RELATIVE reloc in .got to contain the
	addend.
	* sysdeps/sparc/sparc64/dl-machine.h (elf_machine_load_address): Use
	the same l_addr computation.
	* sysdeps/sparc/sparc64/configure.in: Removed.
	* sysdeps/sparc/sparc64/configure: Removed.
	* config.h.in (SPARC64_DYNAMIC_BEFORE_GOT): Remove.

--- libc/sysdeps/sparc/sparc32/dl-machine.h.jj	Thu Aug 29 11:09:59 2002
+++ libc/sysdeps/sparc/sparc32/dl-machine.h	Tue Sep 24 14:43:05 2002
@@ -101,21 +101,20 @@ elf_machine_dynamic (void)
 static inline Elf32_Addr
 elf_machine_load_address (void)
 {
-  register Elf32_Addr pc __asm("%o7"), pic __asm("%l7"), got;
+  register Elf32_Addr *pc __asm ("%o7"), *got __asm ("%l7");
 
-  LOAD_PIC_REG (pic);
+  __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"
+	 "call 1f\n\t"
+	 " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"
+	 "call _DYNAMIC\n\t"
+	 "call _GLOBAL_OFFSET_TABLE_\n"
+	 "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));
 
-  /* Utilize the fact that a local .got entry will be partially
-     initialized at startup awaiting its RELATIVE fixup.  */
-
-  __asm("sethi %%hi(.Load_address),%1\n"
-        ".Load_address:\n\t"
-        "call 1f\n\t"
-        "or %1,%%lo(.Load_address),%1\n"
-        "1:\tld [%2+%1],%1"
-        : "=r"(pc), "=r"(got) : "r"(pic));
-
-  return pc - got;
+  /* got is now l_addr + _GLOBAL_OFFSET_TABLE_
+     *got is _DYNAMIC
+     pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8
+     pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12  */
+  return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4;
 }
 
 /* Set up the loaded object described by L so its unrelocated PLT
--- libc/sysdeps/sparc/sparc64/configure.jj	Mon Mar 11 19:33:57 2002
+++ libc/sysdeps/sparc/sparc64/configure	Tue Sep 24 14:46:29 2002
@@ -1,33 +0,0 @@
- # Local configure fragment for sysdeps/sparc/sparc64.
-
-# Check whether .got section comes before or after .dynamic
-echo $ac_n "checking where sparc64 .dynamic section comes before .got""... $ac_c" 1>&6
-echo "configure:6: checking where sparc64 .dynamic section comes before .got" >&5
-if eval "test \"`echo '$''{'libc_cv_sparc64_dynamic_before_got'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  
-${CC-cc} $CFLAGS -shared -Wl,--verbose 2>&1 \
-  | grep '^[ 	]*\.\(got\|dynamic\)[^A-Za-z0-9_]' > conftest.order
-
-if test `cat conftest.order | wc -l` != 2; then
-  { echo "configure: error: Couldn't figure .got/.dynamic relative placement" 1>&2; exit 1; }
-else
-  
-  if head -n 1 conftest.order | grep '^[ 	]*\.got'; then
-    libc_cv_sparc64_dynamic_before_got=no
-  else
-    libc_cv_sparc64_dynamic_before_got=yes
-  fi
-  
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$libc_cv_sparc64_dynamic_before_got" 1>&6
-if test $libc_cv_sparc64_dynamic_before_got = yes; then
-  cat >> confdefs.h <<\EOF
-#define SPARC64_DYNAMIC_BEFORE_GOT 1
-EOF
-
-fi
--- libc/sysdeps/sparc/sparc64/dl-machine.h.jj	Wed Jun  5 04:27:51 2002
+++ libc/sysdeps/sparc/sparc64/dl-machine.h	Tue Sep 24 14:40:18 2002
@@ -68,44 +68,21 @@ elf_machine_dynamic (void)
 static inline Elf64_Addr
 elf_machine_load_address (void)
 {
-  register Elf64_Addr *elf_pic_register __asm__("%l7");
+  register Elf32_Addr *pc __asm ("%o7");
+  register Elf64_Addr *got __asm ("%l7");
 
-  LOAD_PIC_REG (elf_pic_register);
-
-  /* We used to utilize the fact that a local .got entry will
-     be partially initialized at startup awaiting its RELATIVE
-     fixup:
-
-     Elf64_Addr pc, la;
-
-     __asm("sethi %%hi(.Load_address), %1\n"
-	   ".Load_address:\n\t"
-	   "rd %%pc, %0\n\t"
-	   "or %1, %%lo(.Load_address), %1\n\t"
-	   : "=r"(pc), "=r"(la));
-
-     return pc - *(Elf64_Addr *)(elf_pic_register + la);
-
-     Unfortunately as binutils tries to work around Solaris
-     dynamic linker bug which resolves R_SPARC_RELATIVE as X += B + A
-     instead of X = B + A this does not work any longer, since ld
-     clears it.
-
-     The following method relies on the fact that sparcv9 ABI maximal
-     page length is 1MB and all ELF segments on sparc64 are aligned
-     to 1MB.  Also assumes that they both fit into the first 1MB of
-     the RW segment.  This should be true for some time unless ld.so
-     grows too much, at the moment the whole stripped ld.so is 128KB
-     and only smaller part of that is in the RW segment.  */
-
-#ifdef SPARC64_DYNAMIC_BEFORE_GOT
-  /* If _DYNAMIC comes before _GLOBAL_OFFSET_TABLE_...  */
-  return ((Elf64_Addr)elf_pic_register - *elf_pic_register) & ~0xfffffUL;
-#else
-  /* ... and if _DYNAMIC comes after _GLOBAL_OFFSET_TABLE_.  */
-  return ((Elf64_Addr)elf_pic_register - *elf_pic_register + 0xfffff)
-	 & ~0xfffffUL;
-#endif
+  __asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t"
+         "call 1f\n\t"
+         " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t"
+         "call _DYNAMIC\n\t"
+         "call _GLOBAL_OFFSET_TABLE_\n"
+         "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got));
+
+  /* got is now l_addr + _GLOBAL_OFFSET_TABLE_
+     *got is _DYNAMIC
+     pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8
+     pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12  */
+  return (Elf64_Addr) got - *got + (Elf32_Sword) ((pc[2] - pc[3]) * 4) - 4;
 }
 
 /* We have 4 cases to handle.  And we code different code sequences
--- libc/sysdeps/sparc/sparc64/configure.in.jj	Mon Mar 11 19:33:30 2002
+++ libc/sysdeps/sparc/sparc64/configure.in	Tue Sep 24 14:46:25 2002
@@ -1,26 +0,0 @@
-sinclude(./aclocal.m4)dnl Autoconf lossage
-GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
-# Local configure fragment for sysdeps/sparc/sparc64.
-
-# Check whether .got section comes before or after .dynamic
-AC_CACHE_CHECK(where sparc64 .dynamic section comes before .got,
-	       libc_cv_sparc64_dynamic_before_got, [dnl
-changequote(,)
-${CC-cc} $CFLAGS -shared -Wl,--verbose 2>&1 \
-  | grep '^[ 	]*\.\(got\|dynamic\)[^A-Za-z0-9_]' > conftest.order
-changequote([,])
-if test `cat conftest.order | wc -l` != 2; then
-  AC_ERROR(Couldn't figure .got/.dynamic relative placement)
-else
-  changequote(,)
-  if head -n 1 conftest.order | grep '^[ 	]*\.got'; then
-    libc_cv_sparc64_dynamic_before_got=no
-  else
-    libc_cv_sparc64_dynamic_before_got=yes
-  fi
-  changequote([,])
-fi
-rm -f conftest*])
-if test $libc_cv_sparc64_dynamic_before_got = yes; then
-  AC_DEFINE(SPARC64_DYNAMIC_BEFORE_GOT)
-fi
--- libc/config.h.in.jj	Tue Aug 27 17:19:40 2002
+++ libc/config.h.in	Tue Sep 24 14:43:52 2002
@@ -175,10 +175,6 @@
 /* Mach/i386 specific: define if the `i386_io_perm_*' RPCs are available.  */
 #undef	HAVE_I386_IO_PERM_MODIFY
 
-/* Sparc64 specific: define if .dynamic section comes before .got for
-   shared libs.  */
-#undef  SPARC64_DYNAMIC_BEFORE_GOT
-
 /*
  */
 

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]