aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/register-dump.h21
-rw-r--r--sysdeps/generic/segfault.c55
-rw-r--r--sysdeps/i386/register-dump.h256
-rw-r--r--sysdeps/powerpc/register-dump.h73
-rw-r--r--sysdeps/unix/sysv/linux/i386/profil-counter.h5
-rw-r--r--sysdeps/unix/sysv/linux/ldd-rewrite.sed2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/chown.c131
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/clone.S78
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/lchown.S35
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/profil-counter.h36
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h24
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/syscalls.list4
-rw-r--r--sysdeps/unix/sysv/linux/sys/mount.h6
13 files changed, 642 insertions, 84 deletions
diff --git a/sysdeps/generic/register-dump.h b/sysdeps/generic/register-dump.h
new file mode 100644
index 0000000000..42c222c2ed
--- /dev/null
+++ b/sysdeps/generic/register-dump.h
@@ -0,0 +1,21 @@
+/* Dump registers.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* In general we cannot do anything. */
diff --git a/sysdeps/generic/segfault.c b/sysdeps/generic/segfault.c
index 6504123e18..090f91a657 100644
--- a/sysdeps/generic/segfault.c
+++ b/sysdeps/generic/segfault.c
@@ -18,16 +18,21 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include <ctype.h>
#include <execinfo.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
/* This file defines macros to access the content of the sigcontext element
passed up by the signal handler. */
#include <sigcontextinfo.h>
+/* Get code to possibly dump the content of all registers. */
+#include <register-dump.h>
+
/* This is a global variable set at program start time. It marks the
highest used stack address. */
extern void *__libc_stack_end;
@@ -76,6 +81,8 @@ catch_segfault (int signal, SIGCONTEXT ctx)
int fd;
void **arr;
size_t cnt;
+ struct sigaction sa;
+ const char *sigstring;
/* This is the name of the file we are writing to. If none is given
or we cannot write to this file write to stderr. */
@@ -88,9 +95,17 @@ catch_segfault (int signal, SIGCONTEXT ctx)
fd = 2;
}
-#define WRITE_STRING(s) write (fd, s, sizeof (s) - 1)
- WRITE_STRING ("*** Segmentation Fault\n");
- WRITE_STRING ("Backtrace:\n");
+#define WRITE_STRING(s) write (fd, s, strlen (s))
+ WRITE_STRING ("*** ");
+ sigstring = strsignal (signal);
+ WRITE_STRING (sigstring);
+ WRITE_STRING ("\n");
+
+#ifdef REGISTER_DUMP
+ REGISTER_DUMP;
+#endif
+
+ WRITE_STRING ("\nBacktrace:\n");
top_frame = GET_FRAME (ctx);
top_stack = GET_STACK (ctx);
@@ -124,8 +139,12 @@ catch_segfault (int signal, SIGCONTEXT ctx)
/* Now generate nicely formatted output. */
__backtrace_symbols_fd (arr, cnt, fd);
- /* Nothing else to do. */
- _exit (128 + SIGSEGV);
+ /* Pass on the signal (so that a core file is produced). */
+ sa.sa_handler = SIG_DFL;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction (signal, &sa, NULL);
+ raise (signal);
}
@@ -134,12 +153,36 @@ __attribute__ ((constructor))
install_handler (void)
{
struct sigaction sa;
+ const char *sigs = getenv ("SEGFAULT_SIGNALS");
sa.sa_handler = (void *) catch_segfault;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART;
- sigaction (SIGSEGV, &sa, NULL);
+ if (sigs == NULL)
+ sigaction (SIGSEGV, &sa, NULL);
+ else if (sigs[0] == '\0')
+ /* Do not do anything. */
+ return;
+ else
+ {
+ const char *where;
+ int all = __strcasecmp (sigs, "all");
+
+#define INSTALL_FOR_SIG(sig, name) \
+ where = __strcasestr (sigs, name); \
+ if (all || (where != NULL \
+ && (where == sigs || !isalnum (where[-1])) \
+ && !isalnum (where[sizeof (name) - 1]))) \
+ sigaction (sig, &sa, NULL);
+
+ INSTALL_FOR_SIG (SIGSEGV, "segv");
+ INSTALL_FOR_SIG (SIGILL, "ill");
+ INSTALL_FOR_SIG (SIGBUS, "bus");
+ INSTALL_FOR_SIG (SIGSTKFLT, "stkflt");
+ INSTALL_FOR_SIG (SIGABRT, "abrt");
+ INSTALL_FOR_SIG (SIGFPE, "fpe");
+ }
/* Maybe we are expected to use an alternative stack. */
if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)
diff --git a/sysdeps/i386/register-dump.h b/sysdeps/i386/register-dump.h
new file mode 100644
index 0000000000..34501fe1be
--- /dev/null
+++ b/sysdeps/i386/register-dump.h
@@ -0,0 +1,256 @@
+/* Dump registers.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <sys/uio.h>
+#include <stdio-common/_itoa.h>
+
+/* We will print the register dump in this format:
+
+ EAX: XXXXXXXX EBX: XXXXXXXX ECX: XXXXXXXX EDX: XXXXXXXX
+ ESI: XXXXXXXX EDI: XXXXXXXX EBP: XXXXXXXX ESP: XXXXXXXX
+
+ EIP: XXXXXXXX EFLAGS: XXXXXXXX
+
+ CS: XXXX DS: XXXX ES: XXXX FS: XXXX GS: XXXX SS: XXXX
+
+ Trap: XXXXXXXX Error: XXXXXXXX OldMask: XXXXXXXX
+ ESP/SIGNAL: XXXXXXXX CR2: XXXXXXXX
+
+ FPUCW: XXXXXXXX FPUSW: XXXXXXXX TAG: XXXXXXXX
+ IPOFF: XXXXXXXX CSSEL: XXXX DATAOFF: XXXXXXXX DATASEL: XXXX
+
+ ST(0) XXXX XXXXXXXXXXXXXXXX ST(1) XXXX XXXXXXXXXXXXXXXX
+ ST(2) XXXX XXXXXXXXXXXXXXXX ST(3) XXXX XXXXXXXXXXXXXXXX
+ ST(4) XXXX XXXXXXXXXXXXXXXX ST(5) XXXX XXXXXXXXXXXXXXXX
+ ST(6) XXXX XXXXXXXXXXXXXXXX ST(7) XXXX XXXXXXXXXXXXXXXX
+
+ */
+
+static void
+hexvalue (unsigned long int value, char *buf, size_t len)
+{
+ char *cp = _itoa_word (value, buf + len, 16, 0);
+ while (cp > buf)
+ *--cp = '0';
+}
+
+static void
+register_dump (int fd, struct sigcontext *ctx)
+{
+ char regs[21][8];
+ char fpregs[31][8];
+ struct iovec iov[97];
+ size_t nr = 0;
+
+#define ADD_STRING(str) \
+ iov[nr].iov_base = (char *) str; \
+ iov[nr].iov_len = strlen (str); \
+ ++nr
+#define ADD_MEM(str, len) \
+ iov[nr].iov_base = str; \
+ iov[nr].iov_len = len; \
+ ++nr
+
+ /* Generate strings of register contents. */
+ hexvalue (ctx->eax, regs[0], 8);
+ hexvalue (ctx->ebx, regs[1], 8);
+ hexvalue (ctx->ecx, regs[2], 8);
+ hexvalue (ctx->edx, regs[3], 8);
+ hexvalue (ctx->esi, regs[4], 8);
+ hexvalue (ctx->edi, regs[5], 8);
+ hexvalue (ctx->ebp, regs[6], 8);
+ hexvalue (ctx->esp, regs[7], 8);
+ hexvalue (ctx->eip, regs[8], 8);
+ hexvalue (ctx->eflags, regs[9], 8);
+ hexvalue (ctx->cs, regs[10], 4);
+ hexvalue (ctx->ds, regs[11], 4);
+ hexvalue (ctx->es, regs[12], 4);
+ hexvalue (ctx->fs, regs[13], 4);
+ hexvalue (ctx->gs, regs[14], 4);
+ hexvalue (ctx->ss, regs[15], 4);
+ hexvalue (ctx->trapno, regs[16], 8);
+ hexvalue (ctx->err, regs[17], 8);
+ hexvalue (ctx->oldmask, regs[18], 8);
+ hexvalue (ctx->esp_at_signal, regs[19], 8);
+ hexvalue (ctx->cr2, regs[20], 8);
+
+ /* Generate the output. */
+ ADD_STRING ("Register dump:\n\n EAX: ");
+ ADD_MEM (regs[0], 8);
+ ADD_STRING (" EBX: ");
+ ADD_MEM (regs[1], 8);
+ ADD_STRING (" ECX: ");
+ ADD_MEM (regs[2], 8);
+ ADD_STRING (" EDX: ");
+ ADD_MEM (regs[3], 8);
+ ADD_STRING ("\n ESI: ");
+ ADD_MEM (regs[4], 8);
+ ADD_STRING (" EDI: ");
+ ADD_MEM (regs[5], 8);
+ ADD_STRING (" EBP: ");
+ ADD_MEM (regs[6], 8);
+ ADD_STRING (" ESP: ");
+ ADD_MEM (regs[7], 8);
+ ADD_STRING ("\n\n EIP: ");
+ ADD_MEM (regs[8], 8);
+ ADD_STRING (" EFLAGS: ");
+ ADD_MEM (regs[9], 8);
+ ADD_STRING ("\n\n CS: ");
+ ADD_MEM (regs[10], 4);
+ ADD_STRING (" DS: ");
+ ADD_MEM (regs[11], 4);
+ ADD_STRING (" ES: ");
+ ADD_MEM (regs[12], 4);
+ ADD_STRING (" FS: ");
+ ADD_MEM (regs[13], 4);
+ ADD_STRING (" GS: ");
+ ADD_MEM (regs[14], 4);
+ ADD_STRING (" SS: ");
+ ADD_MEM (regs[15], 4);
+ ADD_STRING ("\n\n Trap: ");
+ ADD_MEM (regs[16], 8);
+ ADD_STRING (" Error: ");
+ ADD_MEM (regs[17], 8);
+ ADD_STRING (" OldMask: ");
+ ADD_MEM (regs[18], 8);
+ ADD_STRING ("\n ESP/signal: ");
+ ADD_MEM (regs[19], 8);
+ ADD_STRING (" CR2: ");
+ ADD_MEM (regs[20], 8);
+
+ if (ctx->fpstate != NULL)
+ {
+
+ /* Generate output for the FPU control/status registers. */
+ hexvalue (ctx->fpstate->cw, fpregs[0], 8);
+ hexvalue (ctx->fpstate->sw, fpregs[1], 8);
+ hexvalue (ctx->fpstate->tag, fpregs[2], 8);
+ hexvalue (ctx->fpstate->ipoff, fpregs[3], 8);
+ hexvalue (ctx->fpstate->cssel, fpregs[4], 4);
+ hexvalue (ctx->fpstate->dataoff, fpregs[5], 8);
+ hexvalue (ctx->fpstate->datasel, fpregs[6], 4);
+
+ ADD_STRING ("\n\n FPUCW: ");
+ ADD_MEM (fpregs[0], 8);
+ ADD_STRING (" FPUSW: ");
+ ADD_MEM (fpregs[1], 8);
+ ADD_STRING (" TAG: ");
+ ADD_MEM (fpregs[2], 8);
+ ADD_STRING ("\n IPOFF: ");
+ ADD_MEM (fpregs[3], 8);
+ ADD_STRING (" CSSEL: ");
+ ADD_MEM (fpregs[4], 4);
+ ADD_STRING (" DATAOFF: ");
+ ADD_MEM (fpregs[5], 8);
+ ADD_STRING (" DATASEL: ");
+ ADD_MEM (fpregs[6], 4);
+
+ /* Now the real FPU registers. */
+ hexvalue (ctx->fpstate->_st[0].exponent, fpregs[7], 8);
+ hexvalue (ctx->fpstate->_st[0].significand[3] << 16
+ | ctx->fpstate->_st[0].significand[2], fpregs[8], 8);
+ hexvalue (ctx->fpstate->_st[0].significand[1] << 16
+ | ctx->fpstate->_st[0].significand[0], fpregs[9], 8);
+ hexvalue (ctx->fpstate->_st[1].exponent, fpregs[10], 8);
+ hexvalue (ctx->fpstate->_st[1].significand[3] << 16
+ | ctx->fpstate->_st[1].significand[2], fpregs[11], 8);
+ hexvalue (ctx->fpstate->_st[1].significand[1] << 16
+ | ctx->fpstate->_st[1].significand[0], fpregs[12], 8);
+ hexvalue (ctx->fpstate->_st[2].exponent, fpregs[13], 8);
+ hexvalue (ctx->fpstate->_st[2].significand[3] << 16
+ | ctx->fpstate->_st[2].significand[2], fpregs[14], 8);
+ hexvalue (ctx->fpstate->_st[2].significand[1] << 16
+ | ctx->fpstate->_st[2].significand[0], fpregs[15], 8);
+ hexvalue (ctx->fpstate->_st[3].exponent, fpregs[16], 8);
+ hexvalue (ctx->fpstate->_st[3].significand[3] << 16
+ | ctx->fpstate->_st[3].significand[2], fpregs[17], 8);
+ hexvalue (ctx->fpstate->_st[3].significand[1] << 16
+ | ctx->fpstate->_st[3].significand[0], fpregs[18], 8);
+ hexvalue (ctx->fpstate->_st[4].exponent, fpregs[19], 8);
+ hexvalue (ctx->fpstate->_st[4].significand[3] << 16
+ | ctx->fpstate->_st[4].significand[2], fpregs[20], 8);
+ hexvalue (ctx->fpstate->_st[4].significand[1] << 16
+ | ctx->fpstate->_st[4].significand[0], fpregs[21], 8);
+ hexvalue (ctx->fpstate->_st[5].exponent, fpregs[22], 8);
+ hexvalue (ctx->fpstate->_st[5].significand[3] << 16
+ | ctx->fpstate->_st[5].significand[2], fpregs[23], 8);
+ hexvalue (ctx->fpstate->_st[5].significand[1] << 16
+ | ctx->fpstate->_st[5].significand[0], fpregs[24], 8);
+ hexvalue (ctx->fpstate->_st[6].exponent, fpregs[25], 8);
+ hexvalue (ctx->fpstate->_st[6].significand[3] << 16
+ | ctx->fpstate->_st[6].significand[2], fpregs[26], 8);
+ hexvalue (ctx->fpstate->_st[6].significand[1] << 16
+ | ctx->fpstate->_st[6].significand[0], fpregs[27], 8);
+ hexvalue (ctx->fpstate->_st[7].exponent, fpregs[28], 8);
+ hexvalue (ctx->fpstate->_st[7].significand[3] << 16
+ | ctx->fpstate->_st[7].significand[2], fpregs[29], 8);
+ hexvalue (ctx->fpstate->_st[7].significand[1] << 16
+ | ctx->fpstate->_st[7].significand[0], fpregs[30], 8);
+
+ ADD_STRING ("\n\n ST(0) ");
+ ADD_MEM (fpregs[7], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[8], 8);
+ ADD_MEM (fpregs[9], 8);
+ ADD_STRING (" ST(1) ");
+ ADD_MEM (fpregs[10], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[11], 8);
+ ADD_MEM (fpregs[12], 8);
+ ADD_STRING ("\n ST(2) ");
+ ADD_MEM (fpregs[13], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[14], 8);
+ ADD_MEM (fpregs[15], 8);
+ ADD_STRING (" ST(3) ");
+ ADD_MEM (fpregs[16], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[17], 8);
+ ADD_MEM (fpregs[18], 8);
+ ADD_STRING ("\n ST(4) ");
+ ADD_MEM (fpregs[19], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[20], 8);
+ ADD_MEM (fpregs[21], 8);
+ ADD_STRING (" ST(5) ");
+ ADD_MEM (fpregs[22], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[23], 8);
+ ADD_MEM (fpregs[24], 8);
+ ADD_STRING ("\n ST(6) ");
+ ADD_MEM (fpregs[25], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[26], 8);
+ ADD_MEM (fpregs[27], 8);
+ ADD_STRING (" ST(7) ");
+ ADD_MEM (fpregs[28], 4);
+ ADD_STRING (" ");
+ ADD_MEM (fpregs[29], 8);
+ ADD_MEM (fpregs[30], 8);
+ }
+
+ ADD_STRING ("\n");
+
+ /* Write the stuff out. */
+ writev (fd, iov, nr);
+}
+
+
+#define REGISTER_DUMP register_dump (fd, &ctx)
diff --git a/sysdeps/powerpc/register-dump.h b/sysdeps/powerpc/register-dump.h
new file mode 100644
index 0000000000..428b6073b9
--- /dev/null
+++ b/sysdeps/powerpc/register-dump.h
@@ -0,0 +1,73 @@
+/* Dump registers.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <sys/uio.h>
+#include <stdio-common/_itoa.h>
+
+static const char *regnames[] =
+{
+ "\nr0 =", " sp =", " r2 =", " r3 =", " r4 =", " r5 =",
+ "\nr6 =", " r7 =", " r8 =", " r9 =", " r10=", " r11=",
+ "\nr12=", " r13=", " r14=", " r15=", " r16=", " r17=",
+ "\nr18=", " r19=", " r20=", " r21=", " r22=", " r23=",
+ "\nr24=", " r25=", " r26=", " r27=", " r28=", " r29=",
+ "\nr30=", " r31=", " nip=", " msr=", " r3*=", " ctr=",
+ "\nlr =", " xer=", " ccr=", " mq =", " trap=",
+ "\naddress of fault=", " dsisr=",
+};
+
+static void
+register_dump (int fd, void **ctx)
+{
+ char buffer[(sizeof (regnames) / sizeof (regnames[0])) * 8];
+ char *bufferpos = buffer + sizeof (buffer);
+ struct iovec iov[(sizeof (regnames) / sizeof (regnames[0])) * 2 + 1];
+ int nr = 0;
+
+#define ADD_STRING(str) \
+ iov[nr].iov_base = (char *) str; \
+ iov[nr].iov_len = strlen (str); \
+ ++nr
+#define ADD_HEX(str, len) \
+ do { \
+ char *s = _itoa_word ((unsigned long int) x, bufferpos, 16, 0); \
+ while (bufferpos - s < 8) \
+ *--s = '0'; \
+ iov[nr].iov_base = s; \
+ iov[nr].iov_len = bufferpos - s; \
+ bufferpos = s; \
+ } while (0)
+
+ /* Generate the output. */
+ ADD_STRING ("Register dump:\n\n");
+ for (i = 0; i < sizeof (regnames) / sizeof (regnames[0]); i++)
+ {
+ ADD_STRING (regnames[i]);
+ ADD_HEX (ctx[i]);
+ }
+
+ /* Write the output. */
+ writev (fd, iov, nr);
+}
+
+
+#define REGISTER_DUMP \
+ ctx += 8; /* FIXME!!!! Why is this necessary? Is it necessary? */ \
+ register_dump (fd, ctx)
diff --git a/sysdeps/unix/sysv/linux/i386/profil-counter.h b/sysdeps/unix/sysv/linux/i386/profil-counter.h
index a24ea19654..50186932be 100644
--- a/sysdeps/unix/sysv/linux/i386/profil-counter.h
+++ b/sysdeps/unix/sysv/linux/i386/profil-counter.h
@@ -18,9 +18,10 @@
Boston, MA 02111-1307, USA. */
#include <signal.h>
+#include <sigcontextinfo.h>
static void
-profil_counter (int signo, struct sigcontext sc)
+profil_counter (int signo, SIGCONTEXT scp)
{
- profil_count ((void *) sc.eip);
+ profil_count ((void *) GET_PC (scp));
}
diff --git a/sysdeps/unix/sysv/linux/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/ldd-rewrite.sed
index 0ad5bc4f93..7b8b6bdee0 100644
--- a/sysdeps/unix/sysv/linux/ldd-rewrite.sed
+++ b/sysdeps/unix/sysv/linux/ldd-rewrite.sed
@@ -1,7 +1,7 @@
/Maybe extra code for non-ELF binaries/a\
file=$1\
# Run the ldd stub.\
- lddlibc4 $file\
+ lddlibc4 "$file"\
# Test the result.\
if test $? -lt 3; then\
return 0;\
diff --git a/sysdeps/unix/sysv/linux/powerpc/chown.c b/sysdeps/unix/sysv/linux/powerpc/chown.c
new file mode 100644
index 0000000000..5f6c3d29ce
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/chown.c
@@ -0,0 +1,131 @@
+/* chown() compatibility.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/syscall.h>
+#include <stdlib.h>
+
+/*
+ In Linux 2.1.x the chown functions have been changed. A new function lchown
+ was introduced. The new chown now follows symlinks - the old chown and the
+ new lchown do not follow symlinks.
+ This file emulates chown() under the old kernels.
+*/
+
+extern int __syscall_chown (const char *__file,
+ uid_t __owner, gid_t __group);
+
+int
+__chown (const char *file, uid_t owner, gid_t group)
+{
+ int err;
+ int old_errno;
+ char link[PATH_MAX+2];
+ char path[2*PATH_MAX+4];
+ int loopct;
+ int filelen;
+ static int libc_old_chown = 0 /* -1=old linux, 1=new linux, 0=unknown */;
+
+ if (libc_old_chown == 1)
+ return __syscall_chown (file, owner, group);
+
+ old_errno = errno;
+
+#ifdef __NR_lchown
+ if (libc_old_chown == 0)
+ {
+ err = __syscall_chown (file, owner, group);
+ if (err != -1 || errno != ENOSYS)
+ {
+ libc_old_chown = 1;
+ return err;
+ }
+ libc_old_chown = -1;
+ }
+#endif
+
+ err = __readlink (file, link, PATH_MAX+1);
+ if (err == -1)
+ {
+ errno = old_errno;
+ return __lchown(file, owner, group);
+ }
+
+ filelen = strlen (file) + 1;
+ if (filelen > sizeof(path))
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ memcpy (path, file, filelen);
+
+ /* 'The system has an arbitrary limit...' In practise, we'll hit
+ ENAMETOOLONG before this, usually. */
+ for (loopct = 0; loopct < 128; loopct++)
+ {
+ int linklen;
+
+ if (err >= PATH_MAX+1)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ link[err] = 0; /* Null-terminate string, just-in-case. */
+
+ linklen = strlen (link) + 1;
+
+ if (link[0] == '/')
+ memcpy (path, link, linklen);
+ else
+ {
+ filelen = strlen (path);
+
+ while (filelen > 1 && path[filelen-1] == '/')
+ filelen--;
+ while (filelen > 0 && path[filelen-1] != '/')
+ filelen--;
+ if (filelen + linklen > sizeof(path))
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ memcpy (path+filelen, link, linklen);
+ }
+
+ err = __readlink(path, link, PATH_MAX+1);
+
+ if (err == -1)
+ {
+ errno = old_errno;
+ return __lchown(path, owner, group);
+ }
+ }
+ errno = ELOOP;
+ return -1;
+}
+
+#if defined PIC && defined DO_VERSIONING
+default_symbol_version (__chown, chown, GLIBC_2.1);
+#else
+weak_alias (__chown, chown)
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/clone.S b/sysdeps/unix/sysv/linux/powerpc/clone.S
index 6209922b6b..69d2c5f586 100644
--- a/sysdeps/unix/sysv/linux/powerpc/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/clone.S
@@ -1,5 +1,5 @@
/* Wrapper around clone system call.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -28,56 +28,60 @@
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
ENTRY(__clone)
- /* Set up stack frame, save registers. */
- stwu %r1,-32(%r1)
/* Check for child_stack == NULL || fn == NULL. */
- cmpwi %cr0,%r4,0
- stw %r31,16(%r1)
- cmpwi %cr1,%r3,0
- stw %r30,20(%r1)
- beq- %cr0,badargs
- beq- %cr1,badargs
+ cmpwi %cr0,%r4,0
+ cmpwi %cr1,%r3,0
+ cror cr0*4+eq,cr1*4+eq,cr0*4+eq
+ beq- %cr0,L(badargs)
+ /* Set up stack frame for parent. */
+ stwu %r1,-32(%r1)
+ stmw %r29,16(%r1)
+
/* Set up stack frame for child. */
- addi %r4,%r4,-16
- clrrwi %r4,%r4,4
- li %r0,0
- stw %r0,0(%r4)
+ clrrwi %r4,%r4,4
+ li %r0,0
+ stwu %r0,-16(%r4)
- /* Save fn, args across syscall. */
- mr %r30,%r3 /* Function in r30. */
- mr %r31,%r6 /* Arguments in r31. */
+ /* Save fn, args, stack across syscall. */
+ mr %r29,%r3 /* Function in r29. */
+ mr %r30,%r4 /* Stack pointer in r30. */
+ mr %r31,%r6 /* Argument in r31. */
/* 'flags' argument is first parameter to clone syscall. (The other
argument is the stack pointer, already in r4.) */
- mr %r3,%r5
+ mr %r3,%r5
/* Do the call. */
DO_CALL(SYS_ify(clone))
- bso- error
- beq child
- /* Parent. Restore registers & return. */
- lwz %r31,16(%r1)
- lwz %r30,20(%r1)
- addi %r1,%r1,32
- blr
+ /* Check for child process. */
+ cmpwi %cr1,%r3,0
+ crandc cr1*4+eq,cr1*4+eq,cr0*4+so
+ bne- %cr1,L(parent) /* The '-' is to minimise the race. */
-child:
+ /* On at least mklinux DR3a5, clone() doesn't actually change
+ the stack pointer. I'm pretty sure this is a bug, because
+ it adds a race condition if a signal is sent to a thread
+ just after it is created (in the previous three instructions). */
+ mr %r1,%r30
/* Call procedure. */
- mtlr %r30
- mr %r3,%r31
- blrl
+ mtctr %r29
+ mr %r3,%r31
+ bctrl
/* Call _exit with result from procedure. */
- b JUMPTARGET(_exit)
-
-badargs:
- li %r3,EINVAL
-error:
- lwz %r31,16(%r1)
- lwz %r30,20(%r1)
- addi %r1,%r1,32
- b JUMPTARGET(__syscall_error)
+ b JUMPTARGET(_exit)
+
+L(parent):
+ /* Parent. Restore registers & return. */
+ lmw %r29,16(%r1)
+ addi %r1,%r1,32
+ bnslr+
+ b JUMPTARGET(__syscall_error)
+
+L(badargs):
+ li %r3,EINVAL
+ b JUMPTARGET(__syscall_error)
END (__clone)
weak_alias (__clone, clone)
diff --git a/sysdeps/unix/sysv/linux/powerpc/lchown.S b/sysdeps/unix/sysv/linux/powerpc/lchown.S
new file mode 100644
index 0000000000..9195eab516
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/lchown.S
@@ -0,0 +1,35 @@
+/* lchown system call.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/* Some old kernel headers call lchown() 'chown'. The number is
+ the same. */
+
+#include <sysdep.h>
+
+#ifdef __NR_lchown
+ PSEUDO (__lchown, lchown, 3)
+#else
+ PSEUDO (__lchown, chown, 3)
+#endif
+ ret
+ PSEUDO_END(__lchown)
+ weak_alias (__lchown, lchown)
+#if defined PIC && defined DO_VERSIONING
+ symbol_version (__lchown, chown, GLIBC_2.0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
index 4be6f11270..8a6a0bcf3d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
+++ b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h
@@ -1,34 +1,2 @@
-/* Low-level statistical profiling support function. Linux/PowerPC version.
- Copyright (C) 1996, 1997 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-#include <sys/ptrace.h>
-
-/* You can also do this by using
- void
- profil_counter (int signo, struct pt_regs *pt)
- {
- profil_count ((void *) pt->nip);
- }
- */
-
-void
-profil_counter (int signo, void **regs)
-{
- profil_count (regs[PT_NIP]);
-}
+/* We can use the ix86 version. */
+#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>
diff --git a/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
new file mode 100644
index 0000000000..2a7a2fe5c8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h
@@ -0,0 +1,24 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <sys/ptrace.h>
+
+#define SIGCONTEXT void **
+#define GET_PC(ctx) ((ctx)[PT_NIP])
+#define GET_FRAME(ctx) (*(void **)(ctx)[PT_R1])
+#define GET_STACK(ctx) ((ctx)[PT_R1])
diff --git a/sysdeps/unix/sysv/linux/powerpc/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/syscalls.list
index 605762a2a4..3af0c5b6f8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/syscalls.list
+++ b/sysdeps/unix/sysv/linux/powerpc/syscalls.list
@@ -1,6 +1,4 @@
# File name Caller Syscall name # args Strong name Weak names
s_llseek llseek _llseek 5 __sys_llseek
-
-getresuid - getresuid 3 getresuid
-getresgid - getresgid 3 getresgid
+s_chown chown chown 3 __syscall_chown
diff --git a/sysdeps/unix/sysv/linux/sys/mount.h b/sysdeps/unix/sysv/linux/sys/mount.h
index f29d158fb5..862c1f0407 100644
--- a/sysdeps/unix/sysv/linux/sys/mount.h
+++ b/sysdeps/unix/sysv/linux/sys/mount.h
@@ -83,7 +83,11 @@ enum
/* Possible value for FLAGS parameter of `umount2'. */
-#define MNT_FORCE /* Force unmounting. */
+enum
+{
+ MNT_FORCE = 1 /* Force unmounting. */
+#define MNT_FORCE MNT_FORCE
+};
__BEGIN_DECLS