summary refs log tree commit diff
path: root/sysdeps/sparc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>1998-04-06 19:08:46 +0000
committerRichard Henderson <rth@redhat.com>1998-04-06 19:08:46 +0000
commit4194bc660f0768b1e0999f4e0a7723a35b00953c (patch)
tree7576ff43a34860662e9cc8f9b6438cd2ff0ac31e /sysdeps/sparc
parenta55400166da3b4713ea9258be7ee739bdbd2d607 (diff)
downloadglibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.tar.gz
glibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.tar.xz
glibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.zip
* elf/dl-runtime.c (fixup, profile_fixup): The final arg to _dl_lookup_*symbol is DL_LOOKUP_NOPLT not ELF_MACHINE_JMP_SLOT. * elf/elf.h (EM_SPARC64): Remove. (EM_SPARC32PLUS, EM_SPARCV9): Add. (HWCAP_SPARC_V9): Add. * elf/ldsodefs.h (_dl_hwcap): Declare. * sysdeps/sparc/sparc32/dl-machine.h (_dl_hwcap, _dl_hwcap_mask): Weaken so dlopen from static progies works. (WEAKADDR): New macro. (elf_machine_matches_host): Accept EM_SPARC32PLUS on a v9 cpu. (LD_SO_PRELOAD): New macro. (elf_machine_fixup_plt): Cope with weak _dl_hwcap. (elf_machine_rela): Weaken _dl_rtld_map. * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: Rename __libc_clone to __clone, and remove the later's alias. * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Copy to/from the kernel's structure.
1998-04-06  Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>

	* elf/dl-runtime.c (fixup, profile_fixup): The final arg to
	_dl_lookup_*symbol is DL_LOOKUP_NOPLT not ELF_MACHINE_JMP_SLOT.

	* elf/elf.h (EM_SPARC64): Remove.
	(EM_SPARC32PLUS, EM_SPARCV9): Add.
	(HWCAP_SPARC_V9): Add.

	* elf/ldsodefs.h (_dl_hwcap): Declare.
	* sysdeps/sparc/sparc32/dl-machine.h (_dl_hwcap, _dl_hwcap_mask):
	Weaken so dlopen from static progies works.
	(WEAKADDR): New macro.
	(elf_machine_matches_host): Accept EM_SPARC32PLUS on a v9 cpu.
	(LD_SO_PRELOAD): New macro.
	(elf_machine_fixup_plt): Cope with weak _dl_hwcap.
	(elf_machine_rela): Weaken _dl_rtld_map.

	* sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: Rename __libc_clone
	to __clone, and remove the later's alias.
	* sysdeps/unix/sysv/linux/sparc/sparc64/clone.S: Likewise.

	* sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Copy to/from
	the kernel's structure.

	* sysdeps/generic/libc-start.c: Allow init and fini to be null.
Diffstat (limited to 'sysdeps/sparc')
-rw-r--r--sysdeps/sparc/sparc32/dl-machine.h55
1 files changed, 46 insertions, 9 deletions
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 224c6bafff..1931c0caa7 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -21,8 +21,8 @@
 
 #include <assert.h>
 #include <string.h>
-#include <link.h>
 #include <sys/param.h>
+#include <elf/ldsodefs.h>
 
 
 /* Some SPARC opcodes we need to use for self-modifying code.  */
@@ -33,11 +33,36 @@
 #define OPCODE_SAVE_SP	0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
 
 
+/* To allow static progies to link properly, define these as weak.  */
+weak_extern(_dl_hwcap);
+weak_extern(_dl_hwcap_mask);
+
+
+/* Protect some broken versions of gcc from misinterpreting weak addresses.  */
+#define WEAKADDR(x)	({ __typeof(x) *_px = &x;			\
+			   __asm ("" : "=r" (_px) : "0" (_px));		\
+			   _px })
+
+
+/* Use a different preload file when running in 32-bit emulation mode
+   on a 64-bit host.  */
+#define LD_SO_PRELOAD ((_dl_hwcap & HWCAP_SPARC_V9) ? "/etc/ld.so.preload32" \
+		       : "/etc/ld.so.preload")
+
+
 /* Return nonzero iff E_MACHINE is compatible with the running host.  */
 static inline int
 elf_machine_matches_host (Elf32_Half e_machine)
 {
-  return e_machine == EM_SPARC;
+  if (e_machine == EM_SPARC)
+    return 1;
+  else if (e_machine == EM_SPARC32PLUS)
+    {
+      unsigned long *hwcap = WEAKADDR(_dl_hwcap);
+      return hwcap && (*hwcap & _dl_hwcap_mask & HWCAP_SPARC_V9);
+    }
+  else
+    return 0;
 }
 
 
@@ -240,7 +265,14 @@ static inline void
 elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
 		       Elf32_Addr *reloc_addr, Elf32_Addr value)
 {
-  extern unsigned long _dl_hwcap;
+#ifndef RTLD_BOOTSTRAP
+  /* Note that we don't mask the hwcap here, as the flush is essential to
+     functionality on those cpu's that implement it.  */
+  unsigned long *hwcap = WEAKADDR(_dl_hwcap);
+  int do_flush = (!hwcap || (*hwcap & HWCAP_SPARC_FLUSH));
+#else
+  int do_flush = 0;
+#endif
 
   /* For thread safety, write the instructions from the bottom and
      flush before we overwrite the critical "b,a".  This of course
@@ -248,16 +280,12 @@ elf_machine_fixup_plt (struct link_map *map, const Elf32_Rela *reloc,
      But we also can't tell if we _can_ use flush, so don't. */
 
   reloc_addr[2] = OPCODE_JMP_G1 | (value & 0x3ff);
-#ifndef RTLD_BOOTSTRAP
-  if (_dl_hwcap & HWCAP_SPARC_FLUSH)
+  if (do_flush)
     __asm __volatile ("flush %0+8" : : "r"(reloc_addr));
-#endif
 
   reloc_addr[1] = OPCODE_SETHI_G1 | (value >> 10);
-#ifndef RTLD_BOOTSTRAP
-  if (_dl_hwcap & HWCAP_SPARC_FLUSH)
+  if (do_flush)
     __asm __volatile ("flush %0+4" : : "r"(reloc_addr));
-#endif
 }
 
 /* Return the final value of a plt relocation.  */
@@ -278,6 +306,15 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 		  const Elf32_Sym *sym, const struct r_found_version *version,
 		  Elf32_Addr *const reloc_addr)
 {
+#ifndef RTLD_BOOTSTRAP
+  /* This is defined in rtld.c, but nowhere in the static libc.a; make the
+     reference weak so static programs can still link.  This declaration
+     cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
+     because rtld.c contains the common defn for _dl_rtld_map, which is
+     incompatible with a weak decl in the same file.  */
+  weak_extern (_dl_rtld_map);
+#endif
+
   if (ELF32_R_TYPE (reloc->r_info) == R_SPARC_RELATIVE)
     {
 #ifndef RTLD_BOOTSTRAP