summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-10-14 05:57:55 +0000
committerJakub Jelinek <jakub@redhat.com>2004-10-14 05:57:55 +0000
commit9869e6ec913e268748f510ab6ec64b8fd62531bc (patch)
treef3f8b9c049c73755d183cc1c1affd34ee8f9772b /sysdeps
parent3ee87ca7d4c813087eeee8b9fd04b7836244a54a (diff)
Updated to fedora-glibc-20041014T0548
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-tls.c2
-rw-r--r--sysdeps/generic/ldsodefs.h40
-rw-r--r--sysdeps/generic/segfault.c88
-rw-r--r--sysdeps/unix/sysv/linux/i386/dl-librecon.h6
-rw-r--r--sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h5
-rw-r--r--sysdeps/unix/sysv/linux/ia64/register-dump.h182
-rw-r--r--sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h4
7 files changed, 236 insertions, 91 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 4fe67da4e1..bf3592e292 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -33,7 +33,7 @@
/* Amount of excess space to allocate in the static TLS area
to allow dynamic loading of modules defining IE-model TLS data. */
-# define TLS_STATIC_SURPLUS 64
+# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100
/* Value used for dtv entries for which the allocation is delayed. */
# define TLS_DTV_UNALLOCATED ((void *) -1l)
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 2b526867ad..f1062e7fa6 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -216,18 +216,27 @@ struct rtld_global
/* Don't change the order of the following elements. 'dl_loaded'
must remain the first element. Forever. */
- /* And a pointer to the map for the main map. */
- EXTERN struct link_map *_dl_loaded;
- /* Number of object in the _dl_loaded list. */
- EXTERN unsigned int _dl_nloaded;
- /* Array representing global scope. */
- EXTERN struct r_scope_elem *_dl_global_scope[2];
- /* Direct pointer to the searchlist of the main object. */
- EXTERN struct r_scope_elem *_dl_main_searchlist;
- /* This is zero at program start to signal that the global scope map is
- allocated by rtld. Later it keeps the size of the map. It might be
- reset if in _dl_close if the last global object is removed. */
- EXTERN size_t _dl_global_scope_alloc;
+/* Non-shared code has no support for multiple namespaces. */
+#ifdef SHARED
+# define DL_NNS 16
+#else
+# define DL_NNS 1
+#endif
+ EXTERN struct link_namespaces
+ {
+ /* And a pointer to the map for the main map. */
+ struct link_map *_ns_loaded;
+ /* Number of object in the _dl_loaded list. */
+ unsigned int _ns_nloaded;
+ /* Array representing global scope. */
+ struct r_scope_elem *_ns_global_scope[2];
+ /* Direct pointer to the searchlist of the main object. */
+ struct r_scope_elem *_ns_main_searchlist;
+ /* This is zero at program start to signal that the global scope map is
+ allocated by rtld. Later it keeps the size of the map. It might be
+ reset if in _dl_close if the last global object is removed. */
+ size_t _ns_global_scope_alloc;
+ } _dl_ns[DL_NNS];
/* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we
@@ -477,7 +486,7 @@ struct rtld_global_ro
char *(*_dl_dst_substitute) (struct link_map *, const char *, char *, int);
struct link_map *(internal_function *_dl_map_object) (struct link_map *,
const char *, int,
- int, int, int);
+ int, int, int, Lmid_t);
void (internal_function *_dl_map_object_deps) (struct link_map *,
struct link_map **,
unsigned int, int, int);
@@ -658,7 +667,8 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
value to allow additional security checks. */
extern struct link_map *_dl_map_object (struct link_map *loader,
const char *name, int preloaded,
- int type, int trace_mode, int mode)
+ int type, int trace_mode, int mode,
+ Lmid_t nsid)
internal_function attribute_hidden;
/* Call _dl_map_object on the dependencies of MAP, and set up
@@ -723,7 +733,7 @@ extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name)
and enter it into the _dl_main_map list. */
extern struct link_map *_dl_new_object (char *realname, const char *libname,
int type, struct link_map *loader,
- int mode)
+ int mode, Lmid_t nsid)
internal_function attribute_hidden;
/* Relocate the given object (if it hasn't already been).
diff --git a/sysdeps/generic/segfault.c b/sysdeps/generic/segfault.c
index 47f2447169..f141fff661 100644
--- a/sysdeps/generic/segfault.c
+++ b/sysdeps/generic/segfault.c
@@ -19,11 +19,13 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <alloca.h>
#include <ctype.h>
#include <errno.h>
#include <execinfo.h>
#include <fcntl.h>
#include <signal.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,9 +35,6 @@
#include <bp-checks.h>
-/* Get the definition of "struct layout". */
-#include <frame.h>
-
/* This file defines macros to access the content of the sigcontext element
passed up by the signal handler. */
#include <sigcontextinfo.h>
@@ -43,35 +42,6 @@
/* Get code to possibly dump the content of all registers. */
#include <register-dump.h>
-/* This implementation assumes a stack layout that matches the defaults
- used by gcc's `__builtin_frame_address' and `__builtin_return_address'
- (FP is the frame pointer register):
-
- +-----------------+ +-----------------+
- FP -> | previous FP --------> | previous FP ------>...
- | | | |
- | return address | | return address |
- +-----------------+ +-----------------+
-
- */
-
-/* Get some notion of the current stack. Need not be exactly the top
- of the stack, just something somewhere in the current frame. */
-#ifndef CURRENT_STACK_FRAME
-# define CURRENT_STACK_FRAME ({ char __csf; &__csf; })
-#endif
-
-/* By default we assume that the stack grows downward. */
-#ifndef INNER_THAN
-# define INNER_THAN <
-#endif
-
-/* By default assume the `next' pointer in struct layout points to the
- next struct layout. */
-#ifndef ADVANCE_STACK_FRAME
-# define ADVANCE_STACK_FRAME(next) BOUNDED_1 ((struct layout *) (next))
-#endif
-
/* We'll use tis a lot. */
#define WRITE_STRING(s) write (fd, s, strlen (s))
@@ -102,13 +72,10 @@ write_strsignal (int fd, int signal)
static void
catch_segfault (int signal, SIGCONTEXT ctx)
{
- struct layout *current;
- void *__unbounded top_frame;
- void *__unbounded top_stack;
- int fd;
+ int fd, cnt, i;
void **arr;
- size_t cnt;
struct sigaction sa;
+ uintptr_t pc;
/* 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. */
@@ -130,41 +97,26 @@ catch_segfault (int signal, SIGCONTEXT ctx)
WRITE_STRING ("\nBacktrace:\n");
- top_frame = GET_FRAME (ctx);
- top_stack = GET_STACK (ctx);
+ /* Get the backtrace. */
+ arr = alloca (256 * sizeof (void *));
+ cnt = backtrace (arr, 256);
- /* First count how many entries we'll have. */
- cnt = 1;
- current = BOUNDED_1 ((struct layout *) top_frame);
- while (!((void *) current INNER_THAN top_stack
- || !((void *) current INNER_THAN __libc_stack_end)))
- {
- ++cnt;
-
- current = ADVANCE_STACK_FRAME (current->next);
- }
-
- arr = alloca (cnt * sizeof (void *));
-
- /* First handle the program counter from the structure. */
- arr[0] = GET_PC (ctx);
-
- current = BOUNDED_1 ((struct layout *) top_frame);
- cnt = 1;
- while (!((void *) current INNER_THAN top_stack
- || !((void *) current INNER_THAN __libc_stack_end)))
- {
- arr[cnt++] = current->return_address;
-
- current = ADVANCE_STACK_FRAME (current->next);
- }
+ /* Now try to locate the PC from signal context in the backtrace.
+ Normally it will be found at arr[2], but it might appear later
+ if there were some signal handler wrappers. Allow a few bytes
+ difference to cope with as many arches as possible. */
+ pc = (uintptr_t) GET_PC (ctx);
+ for (i = 0; i < cnt; ++i)
+ if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
+ break;
- /* If the last return address was NULL, assume that it doesn't count. */
- if (arr[cnt-1] == NULL)
- cnt--;
+ /* If we haven't found it, better dump full backtrace even including
+ the signal handler frames instead of not dumping anything. */
+ if (i == cnt)
+ i = 0;
/* Now generate nicely formatted output. */
- __backtrace_symbols_fd (arr, cnt, fd);
+ __backtrace_symbols_fd (arr + i, cnt - i, fd);
#ifdef HAVE_PROC_SELF
/* Now the link map. */
diff --git a/sysdeps/unix/sysv/linux/i386/dl-librecon.h b/sysdeps/unix/sysv/linux/i386/dl-librecon.h
index 5e41977dde..9f52031518 100644
--- a/sysdeps/unix/sysv/linux/i386/dl-librecon.h
+++ b/sysdeps/unix/sysv/linux/i386/dl-librecon.h
@@ -28,15 +28,15 @@
/* We have to find out whether the binary is linked against \
libc 5 or glibc. We do this by looking at all the DT_NEEDED \
entries. If one is libc.so.5 this is a libc 5 linked binary. */ \
- if (GL(dl_loaded)->l_info[DT_NEEDED]) \
+ if (main_map->l_info[DT_NEEDED]) \
{ \
/* We have dependencies. */ \
const ElfW(Dyn) *d; \
const char *strtab; \
\
- strtab = (const char *) D_PTR (GL(dl_loaded), l_info[DT_STRTAB]); \
+ strtab = (const char *) D_PTR (main_map, l_info[DT_STRTAB]); \
\
- for (d = GL(dl_loaded)->l_ld; d->d_tag != DT_NULL; ++d) \
+ for (d = main_map->l_ld; d->d_tag != DT_NULL; ++d) \
if (d->d_tag == DT_NEEDED \
&& strcmp (strtab + d->d_un.d_val, "libc.so.5") == 0) \
break; \
diff --git a/sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h b/sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h
index 61eb67c075..72c60ec240 100644
--- a/sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h
+++ b/sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2003, 2004
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jes Sorensen <jes@linuxcare.com>, July 2000
@@ -36,7 +37,7 @@ struct ia64_fpreg
struct sigcontext
{
- unsigned long int sc_flags; /* see manifest constants above */
+ unsigned long int sc_flags; /* see manifest constants below */
unsigned long int sc_nat; /* bit i == 1 iff scratch reg gr[i] is a NaT */
stack_t sc_stack; /* previously active stack */
diff --git a/sysdeps/unix/sysv/linux/ia64/register-dump.h b/sysdeps/unix/sysv/linux/ia64/register-dump.h
new file mode 100644
index 0000000000..513db974f8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/ia64/register-dump.h
@@ -0,0 +1,182 @@
+/* Dump registers.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <string.h>
+#include <sys/uio.h>
+#include <stdio-common/_itoa.h>
+
+/* We will print the register dump in this format:
+
+ GP: XXXXXXXXXXXXXXXX R2: XXXXXXXXXXXXXXXX R3: XXXXXXXXXXXXXXXX
+ R8: XXXXXXXXXXXXXXXX R9: XXXXXXXXXXXXXXXX R10: XXXXXXXXXXXXXXXX
+ R11: XXXXXXXXXXXXXXXX SP: XXXXXXXXXXXXXXXX TP: XXXXXXXXXXXXXXXX
+ R14: XXXXXXXXXXXXXXXX R15: XXXXXXXXXXXXXXXX R16: XXXXXXXXXXXXXXXX
+ R17: XXXXXXXXXXXXXXXX R18: XXXXXXXXXXXXXXXX R19: XXXXXXXXXXXXXXXX
+ R20: XXXXXXXXXXXXXXXX R21: XXXXXXXXXXXXXXXX R22: XXXXXXXXXXXXXXXX
+ R23: XXXXXXXXXXXXXXXX R24: XXXXXXXXXXXXXXXX R25: XXXXXXXXXXXXXXXX
+ R26: XXXXXXXXXXXXXXXX R27: XXXXXXXXXXXXXXXX R28: XXXXXXXXXXXXXXXX
+ R29: XXXXXXXXXXXXXXXX R30: XXXXXXXXXXXXXXXX R31: XXXXXXXXXXXXXXXX
+
+ RP: XXXXXXXXXXXXXXXX B6: XXXXXXXXXXXXXXXX B7: XXXXXXXXXXXXXXXX
+
+ IP: XXXXXXXXXXXXXXXX RSC: XXXXXXXXXXXXXXXX PR: XXXXXXXXXXXXXXXX
+ PFS: XXXXXXXXXXXXXXXX UNAT: XXXXXXXXXXXXXXXX CFM: XXXXXXXXXXXXXXXX
+ CCV: XXXXXXXXXXXXXXXX FPSR: XXXXXXXXXXXXXXXX
+
+ F32: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX F33: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ F34: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX F35: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+...
+ F124: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX F125: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ F126: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX F127: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+ */
+
+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
+regvalue (unsigned long int *value, char letter, int regno, char *buf)
+{
+ int n = regno >= 100 ? 3 : regno >= 10 ? 2 : 1;
+ buf[0] = ' ';
+ buf[1] = letter;
+ _itoa_word (regno, buf + 2 + n, 10, 0);
+ buf[2 + n] = ':';
+ for (++n; n <= 4; ++n)
+ buf[2 + n] = ' ';
+ hexvalue (value[0], buf + 7, 16);
+ if (letter == 'F')
+ {
+ hexvalue (value[1], buf + 7 + 16, 16);
+ buf[7 + 32] = '\n';
+ }
+ else
+ buf[7 + 16] = '\n';
+}
+
+static void
+register_dump (int fd, struct sigcontext *ctx)
+{
+ char gpregs[32 - 5][8 + 16];
+ char fpregs[128 - 32][8 + 32];
+ char bpregs[3][8 + 16];
+ char spregs[8][16];
+ struct iovec iov[146];
+ size_t nr = 0;
+ int i;
+
+#define ADD_STRING(str) \
+ do \
+ { \
+ iov[nr].iov_base = (char *) str; \
+ iov[nr].iov_len = strlen (str); \
+ ++nr; \
+ } \
+ while (0)
+#define ADD_MEM(str, len) \
+ do \
+ { \
+ iov[nr].iov_base = str; \
+ iov[nr].iov_len = len; \
+ ++nr; \
+ } \
+ while (0)
+
+ /* Generate strings of register contents. */
+ for (i = 1; i < 4; ++i)
+ {
+ regvalue (&ctx->sc_gr[i], 'R', i, gpregs[i - 1]);
+ if (ctx->sc_nat & (1L << i))
+ memcpy (gpregs[i - 1] + 7, "NaT ", 16);
+ }
+ for (i = 8; i < 32; ++i)
+ {
+ regvalue (&ctx->sc_gr[i], 'R', i, gpregs[i - 5]);
+ if (ctx->sc_nat & (1L << i))
+ memcpy (gpregs[i - 1] + 7, "NaT ", 16);
+ }
+ memcpy (gpregs[0] + 1, "GP:", 3);
+ memcpy (gpregs[7] + 1, "SP: ", 4);
+ memcpy (gpregs[8] + 1, "TP: ", 4);
+
+ regvalue (&ctx->sc_br[0], 'B', 0, bpregs[0]);
+ regvalue (&ctx->sc_br[6], 'B', 6, bpregs[1]);
+ regvalue (&ctx->sc_br[7], 'B', 7, bpregs[2]);
+ memcpy (bpregs[0] + 1, "RP:", 3);
+
+ if (ctx->sc_flags & IA64_SC_FLAG_FPH_VALID)
+ for (i = 32; i < 128; ++i)
+ regvalue (&ctx->sc_fr[i].u.bits[0], 'F', i, fpregs[i - 32]);
+
+ hexvalue (ctx->sc_ip, spregs[0], sizeof (spregs[0]));
+ hexvalue (ctx->sc_ar_rsc, spregs[1], sizeof (spregs[1]));
+ hexvalue (ctx->sc_pr, spregs[2], sizeof (spregs[2]));
+ hexvalue (ctx->sc_ar_pfs, spregs[3], sizeof (spregs[3]));
+ hexvalue (ctx->sc_ar_unat, spregs[4], sizeof (spregs[4]));
+ hexvalue (ctx->sc_cfm, spregs[5], sizeof (spregs[5]));
+ hexvalue (ctx->sc_ar_ccv, spregs[6], sizeof (spregs[6]));
+ hexvalue (ctx->sc_ar_fpsr, spregs[7], sizeof (spregs[7]));
+
+ /* Generate the output. */
+ ADD_STRING ("Register dump:\n\n");
+
+ for (i = 0; i < 32 - 5; ++i)
+ ADD_MEM (gpregs[i], sizeof (gpregs[0]) - 1 + ((i % 3) == 2));
+ ADD_STRING ("\n");
+
+ for (i = 0; i < 3; ++i)
+ ADD_MEM (bpregs[i], sizeof (bpregs[0]) - 1);
+
+ ADD_STRING ("\n\n IP: ");
+ ADD_MEM (spregs[0], sizeof (spregs[0]));
+ ADD_STRING (" RSC: ");
+ ADD_MEM (spregs[1], sizeof (spregs[0]));
+ ADD_STRING (" PR: ");
+ ADD_MEM (spregs[2], sizeof (spregs[0]));
+ ADD_STRING ("\n PFS: ");
+ ADD_MEM (spregs[3], sizeof (spregs[0]));
+ ADD_STRING (" UNAT: ");
+ ADD_MEM (spregs[4], sizeof (spregs[0]));
+ ADD_STRING (" CFM: ");
+ ADD_MEM (spregs[5], sizeof (spregs[0]));
+ ADD_STRING ("\n CCV: ");
+ ADD_MEM (spregs[6], sizeof (spregs[0]));
+ ADD_STRING (" FPSR: ");
+ ADD_MEM (spregs[7], sizeof (spregs[0]));
+ ADD_STRING ("\n");
+
+ if (ctx->sc_flags & IA64_SC_FLAG_FPH_VALID)
+ {
+ ADD_STRING ("\n");
+
+ for (i = 0; i < 128 - 32; ++i)
+ ADD_MEM (fpregs[i], sizeof (fpregs[0]) - 1 + (i & 1));
+ }
+
+ /* Write the stuff out. */
+ writev (fd, iov, nr);
+}
+
+
+#define REGISTER_DUMP register_dump (fd, ctx)
diff --git a/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h b/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
index b5ce1d9108..51c11e6b46 100644
--- a/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2004 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
@@ -18,7 +18,7 @@
#define SIGCONTEXT siginfo_t *_si, struct sigcontext *
#define SIGCONTEXT_EXTRA_ARGS _si,
-#define GET_PC(ctx) ((void *) 0)
+#define GET_PC(ctx) ((ctx)->sc_ip)
#define GET_FRAME(ctx) ((void *) 0)
#define GET_STACK(ctx) ((void *) 0)