* elf/dl-runtime.c (fixup, profile_fixup): The final arg to _dl_looku...
authorRichard Henderson <rth@redhat.com>
Mon, 6 Apr 1998 19:08:46 +0000 (19:08 +0000)
committerRichard Henderson <rth@redhat.com>
Mon, 6 Apr 1998 19:08:46 +0000 (19:08 +0000)
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.

ChangeLog
elf/dl-runtime.c
elf/elf.h
elf/ldsodefs.h
sysdeps/generic/libc-start.c
sysdeps/sparc/sparc32/dl-machine.h
sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
sysdeps/unix/sysv/linux/sparc/sparc32/socket.S
sysdeps/unix/sysv/linux/sparc/sparc64/clone.S

index 93fc41c..1d6a994 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,32 @@
+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.
+
 1998-04-06  Richard Henderson  <rth@cygnus.com>
 
+       * sysdeps/generic/libc-start.c: Allow init and fini to be null.
+
        * sysdeps/sparc/sparc32/elf.S: Rewrite for __libc_start_main.
        * sysdeps/sparc/sparc64/elf.S: Likewise.
 
index 53601b8..10daa98 100644 (file)
@@ -128,13 +128,13 @@ fixup (
          {
            value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
                                                &sym, scope, l->l_name,
-                                               version, ELF_MACHINE_JMP_SLOT);
+                                               version, DL_LOOKUP_NOPLT);
            break;
          }
       }
     case 0:
       value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
-                                l->l_name, ELF_MACHINE_JMP_SLOT);
+                                l->l_name, DL_LOOKUP_NOPLT);
     }
 
   /* Currently value contains the base load address of the object
@@ -205,13 +205,13 @@ profile_fixup (
                value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
                                                    &sym, scope, l->l_name,
                                                    version,
-                                                   ELF_MACHINE_JMP_SLOT);
+                                                   DL_LOOKUP_NOPLT);
                break;
              }
          }
        case 0:
          value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
-                                    l->l_name, ELF_MACHINE_JMP_SLOT);
+                                    l->l_name, DL_LOOKUP_NOPLT);
        }
 
       /* Currently value contains the base load address of the object
index 037abab..fcc8a53 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -162,11 +162,14 @@ typedef struct
 #define EM_S370                9               /* Amdahl */
 #define EM_MIPS_RS4_BE 10              /* MIPS R4000 big-endian */
 
-#define EM_SPARC64     11              /* SPARC v9 (not official) 64-bit */
-
 #define EM_PARISC      15              /* HPPA */
+
+#define EM_SPARC32PLUS 18              /* Sun's "v8plus" */
+
 #define EM_PPC         20              /* PowerPC */
 
+#define EM_SPARCV9     43              /* SPARC v9 64-bit */
+
 /* If it is necessary to assign new unofficial EM_* values, please
    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
    chances of collision with official or non-GNU unofficial values.  */
@@ -808,6 +811,7 @@ typedef struct
 #define HWCAP_SPARC_STBAR      2
 #define HWCAP_SPARC_SWAP       4
 #define HWCAP_SPARC_MULDIV     8
+#define HWCAP_SPARC_V9         16      /* The cpu is v9, so v8plus is ok.  */
 
 /* MIPS R3000 specific definitions.  */
 
index 39f2833..19d931f 100644 (file)
@@ -140,6 +140,9 @@ extern int _dl_debug_files;
 /* Expect cache ID.  */
 extern int _dl_correct_cache_id;
 
+/* Mask for hardware capabilities that are available.  */
+extern unsigned long int _dl_hwcap;
+
 /* Mask for important hardware capabilities we honour. */
 extern unsigned long int _dl_hwcap_mask;
 
index 2e777a8..3225a7c 100644 (file)
@@ -40,13 +40,13 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
   __libc_multiple_libcs = dummy_addr && !_dl_starting_up;
 #endif
 
+  /* Set the global _environ variable correctly.  */
+  __environ = &argv[argc + 1];
+
   /* Register the destructor of the dynamic linker if there is any.  */
   if (rtld_fini != NULL)
     atexit (rtld_fini);
 
-  /* Set the global _environ variable correctly.  */
-  __environ = &argv[argc + 1];
-
   /* Call the initializer of the libc.  */
 #ifdef PIC
   if (_dl_debug_impcalls)
@@ -54,15 +54,17 @@ __libc_start_main (int (*main) (int, char **, char **), int argc,
 #endif
   __libc_init_first (argc, argv, __environ);
 
-  /* Call the initializer of the program.  */
+  /* Register the destructor of the program, if any.  */
+  if (fini)
+    atexit (fini);
+
+  /* Call the initializer of the program, if any.  */
 #ifdef PIC
   if (_dl_debug_impcalls)
     _dl_debug_message (1, "\ninitialize program: ", argv[0], "\n\n", NULL);
 #endif
-  (*init) ();
-
-  /* Register the destructor of the program.  */
-  atexit (fini);
+  if (init)
+    (*init) ();
 
 #ifdef PIC
   if (_dl_debug_impcalls)
index 224c6ba..1931c0c 100644 (file)
@@ -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.  */
 #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
index 64735e9..e053569 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
    Contributed by Richard Henderson (rth@tamu.edu).
 
    The GNU C Library is free software; you can redistribute it and/or
 
        .text
        .align  4
-       .globl  __libc_clone
-       .type   __libc_clone,@function
-       .weak   clone
-       __clone = __libc_clone
-       clone   = __libc_clone
+       .globl  __clone
+       .type   __clone,@function
 
-__libc_clone:
+__clone:
        save    %sp,-96,%sp
 
        /* sanity check arguments */
        tst     %i0
-       be      __clone_syscall_error
-       tst     %i1
-       be      __clone_syscall_error
-       nop
+       be      .Lerror
+        tst    %i1
+       be      .Lerror
+        nop
 
        /* Do the system call */
        mov     %i1,%o1
@@ -48,23 +45,31 @@ __libc_clone:
        set     __NR_clone,%g1
        ta      0x10
        bcs     __clone_syscall_error
-       tst     %o1
+        tst    %o1
        bne     __thread_start
-       nop
+        nop
        mov     %o0,%i0
        ret
-       restore
+        restore
 
-__clone_syscall_error:
+.Lerror:
        call    __errno_location
-       set     EINVAL,%i0
+        set    EINVAL,%i0
        st      %i0,[%o0]
        mov     -1,%i0
        ret
-       restore
+        restore
+
+       .size   __clone, .-__clone
+
+       .type   __thread_start,@function
 
 __thread_start:
        call    %i0
-       mov     %i3,%o0
+        mov    %i3,%o0
        call    _exit,0
-       nop
+        nop
+
+       .size   __thread_start, .-__thread_start
+
+weak_alias(__clone, clone)
index 0fab662..b9c20dd 100644 (file)
 #include <syscall.h>
 #include <sys/signal.h>
 #include <errno.h>
+#include <kernel_sigaction.h>
 
 /* The variable is shared between all wrappers around signal handling
    functions which have RT equivalents.  */
 int __libc_missing_rt_sigs;
 
-/* Commented out while I figure out what the fuck goes on */
-long ____sig_table [NSIG];
-#if 0
-
-/* The kernel will deliver signals in the old way if the signal
-   number is a positive number.  The kernel will deliver a signal
-   with the new stack layout if the signal number is a negative number.
-
-   Our sigaction code takes care of selecting the type of kernel we are
-   using at runtime.  */
-
-extern void ____sparc_signal_trampoline (int);
-
 int
-__trampoline_sigaction (int sig, struct sigaction *new, struct sigaction *old)
+__sigaction (int sig, __const struct sigaction *act, struct sigaction *oact)
 {
   int ret;
-  int need_to_hide_trick = 0;
-  __sighandler_t old_sh;
+  struct kernel_sigaction k_sigact, k_osigact;
 
-  if (new)
+  /* Magic to tell the kernel we are using "new-style" signals, in that
+     the signal table is not kept in userspace.  Not the same as the 
+     really-new-style rt signals.  */
+  sig = -sig;
+
+  if (act)
     {
-      if (new->sa_handler != SIG_DFL && new->sa_handler != SIG_IGN)
-       {
-         old_sh = ____sig_table[sig];
-         ____sig_table[sig] = (long int) new->sa_handler;
-         new->sa_handler = ____sparc_signal_trampoline;
-         need_to_hide_trick = 1;
-       }
+      k_sigact.sa_handler = act->sa_handler;
+      k_sigact.sa_mask = act->sa_mask.__val[0];
+      k_sigact.sa_flags = act->sa_flags;
     }
-  __asm__("or %%g0,%0,%%g1\n\t"
-         "or %%g0,%1,%%o0\n\t"
-         "or %%g0,%2,%%o1\n\t"
-         "or %%g0,%3,%%o2\n\t"
-         "t  0x10\n\t"
-         "bcc 1f\n\t"
-         "or %%o0, %%g0, %0\n\t"
-         "sub %%g0, %%o0, %0\n\t"
-         "1:"
-         : "=r" (ret), "=r" ((long int) sig), "=r" ((long int) new),
-           "=r" ((long int) old)
-         : "0" (__NR_sigaction), "1" (sig), "2" (new), "3" (old)
-         : "g1", "o0", "o1", "o2");
+
+  {
+    register int r_syscallnr __asm__("%g1") = __NR_sigaction;
+    register int r_sig __asm__("%o0") = sig;
+    register struct kernel_sigaction *r_act __asm__("%o1");
+    register struct kernel_sigaction *r_oact __asm__("%o2");
+
+    r_act = act ? &k_sigact : NULL;
+    r_oact = oact ? &k_osigact : NULL;
+
+    __asm__ __volatile__("t 0x10\n\t"
+                        "bcc 1f\n\t"
+                        " nop\n\t"
+                        " sub %%g0,%%o0,%%o0\n"
+                        "1:"
+                        : "=r"(r_sig)
+                        : "r"(r_syscallnr), "r"(r_act), "r"(r_oact),
+                          "0"(r_sig));
+
+    ret = r_sig;
+  }
 
   if (ret >= 0)
     {
-      if (old && old->sa_handler == ____sparc_signal_trampoline)
+      if (oact)
        {
-         if (need_to_hide_trick)
-           old->sa_handler = old_sh;
-         else
-           old->sa_handler = ____sig_table[sig];
+         oact->sa_handler = k_osigact.sa_handler;
+         oact->sa_mask.__val[0] = k_osigact.sa_mask;
+         oact->sa_flags = k_osigact.sa_flags;
+         oact->sa_restorer = NULL;
        }
-      if (need_to_hide_trick)
-       new->sa_handler = ____sig_table[sig];
       return 0;
     }
-  __set_errno (-ret);
-  return -1;
-}
-#else
-#    define __new_sigaction __sigaction
-#endif
 
-int
-__new_sigaction (int sig, __const struct sigaction *new, struct sigaction *old)
-{
-  int ret;
-
-  sig = -sig;
-
-  __asm__("or %%g0,%0,%%g1\n\t"
-         "or %%g0,%1,%%o0\n\t"
-         "or %%g0,%2,%%o1\n\t"
-         "or %%g0,%3,%%o2\n\t"
-         "t  0x10\n\t"
-         "bcc 1f\n\t"
-         "or %%o0, %%g0, %0\n\t"
-         "sub %%g0,%%o0,%0\n\t"
-         "1:"
-         : "=r" (ret), "=r" ((long int) sig), "=r" ((long int) new),
-           "=r" ((long int) old)
-         : "0" (__NR_sigaction), "1" (sig), "2" (new), "3" (old)
-         : "g1", "o0", "o1", "o2");
-  if (ret >= 0)
-    return 0;
   __set_errno (-ret);
   return -1;
 }
 
-#if 0
-int
-__sigaction (int sig, __const struct sigaction *new, struct sigaction *old)
-{
-  static (*sigact_routine) (int, __const struct sigaction *, struct sigaction *);
-  int ret;
-  struct sigaction sa;
-
-  if (sigact_routine)
-    return (*sigact_routine) (sig, new, old);
-
-  ret = __new_sigaction (1, NULL, &sa);
-  if (ret == -1)
-    sigact_routine = __trampoline_sigaction;
-  else
-    sigact_routine = __new_sigaction;
-
-  return __sigaction (sig, new, old);
-}
-#endif
-
 weak_alias (__sigaction, sigaction);
index 8d6fd77..a6cb324 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Miguel de Icaza <miguel@gnu.ai.mit.edu>, 1997.
 
index a16f9b7..6c619fc 100644 (file)
 
        .text
        .align  4
-       .globl  __libc_clone
-       .type   __libc_clone,@function
-       .weak   clone
-       __clone = __libc_clone
-       clone   = __libc_clone
+       .globl  __clone
+       .type   __clone,@function
 
-__libc_clone:
+__clone:
        save    %sp,-160,%sp
 
        /* sanity check arguments */
@@ -77,7 +74,7 @@ __libc_clone:
        mov     -1,%i0
        ret
         restore
-       .size __libc_clone, .-__libc_clone
+       .size __clone, .-__clone
 
        .type __thread_start,@function
 __thread_start:
@@ -88,3 +85,5 @@ __thread_start:
        call    _exit,0
         nop
        .size __thread_start, .-__thread_start
+
+weak_alias(__clone, clone)