public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] New sparc* elf_machine_load_address
@ 2002-09-24  8:19 Jakub Jelinek
  2002-09-24 14:47 ` David S. Miller
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2002-09-24  8:19 UTC (permalink / raw)
  To: Roland McGrath, Ulrich Drepper, davem; +Cc: Glibc hackers

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
-
 /*
 \f */
 

	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] New sparc* elf_machine_load_address
  2002-09-24  8:19 [PATCH] New sparc* elf_machine_load_address Jakub Jelinek
@ 2002-09-24 14:47 ` David S. Miller
  0 siblings, 0 replies; 2+ messages in thread
From: David S. Miller @ 2002-09-24 14:47 UTC (permalink / raw)
  To: jakub; +Cc: roland, drepper, libc-hacker

   From: Jakub Jelinek <jakub@redhat.com>
   Date: Tue, 24 Sep 2002 17:19:31 +0200

   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).
   
It's a few cycles at startup, no big deal.

I guess the binutils change could not be done keeping backwards compat
with existing Linux glibc?  I know people like Ben Collins et al.  are
going to hit this if they update binutils and keep whatever glibc
sources they use right now.

So I don't know how nice it is to break older glibc with a binutils
update like that.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-09-24 21:47 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-24  8:19 [PATCH] New sparc* elf_machine_load_address Jakub Jelinek
2002-09-24 14:47 ` David S. Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).