aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
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
parenta55400166da3b4713ea9258be7ee739bdbd2d607 (diff)
downloadglibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.tar
glibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.tar.gz
glibc-4194bc660f0768b1e0999f4e0a7723a35b00953c.tar.bz2
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')
-rw-r--r--sysdeps/generic/libc-start.c18
-rw-r--r--sysdeps/sparc/sparc32/dl-machine.h55
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/clone.S43
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c131
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/socket.S2
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/clone.S13
6 files changed, 125 insertions, 137 deletions
diff --git a/sysdeps/generic/libc-start.c b/sysdeps/generic/libc-start.c
index 2e777a84d2..3225a7ce5d 100644
--- a/sysdeps/generic/libc-start.c
+++ b/sysdeps/generic/libc-start.c
@@ -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)
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
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
index 64735e9dbc..e053569650 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S
@@ -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
@@ -26,21 +26,18 @@
.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)
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
index 0fab662064..b9c20ddcd0 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c
@@ -21,120 +21,65 @@
#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);
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S b/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S
index 8d6fd77c10..a6cb324363 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/socket.S
@@ -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.
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
index a16f9b7c9b..6c619fcdc3 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S
@@ -26,13 +26,10 @@
.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)