mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
Update.
2004-10-12 Jakub Jelinek <jakub@redhat.com> * sysdeps/generic/segfault.c: Include alloca.h and stdint.h. Don't include frame.h. (CURRENT_STACK_FRAME, INNER_THAN, ADVANCE_STACK_FRAME): Remove. (catch_segfault): Use backtrace function. * sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h: Fix comment. * sysdeps/unix/sysv/linux/ia64/register-dump.h: New file. * sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h (GET_PC): Return sc_ip field.
This commit is contained in:
parent
c0f62c5678
commit
c701ab9f0e
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
||||
2004-10-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* sysdeps/generic/segfault.c: Include alloca.h and stdint.h.
|
||||
Don't include frame.h.
|
||||
(CURRENT_STACK_FRAME, INNER_THAN, ADVANCE_STACK_FRAME): Remove.
|
||||
(catch_segfault): Use backtrace function.
|
||||
|
||||
* sysdeps/unix/sysv/linux/ia64/bits/sigcontext.h: Fix comment.
|
||||
* sysdeps/unix/sysv/linux/ia64/register-dump.h: New file.
|
||||
* sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h (GET_PC): Return sc_ip
|
||||
field.
|
||||
|
||||
2004-10-13 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
Add support for namespaces in the dynamic linker.
|
||||
|
@ -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;
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
@ -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 */
|
||||
|
||||
|
182
sysdeps/unix/sysv/linux/ia64/register-dump.h
Normal file
182
sysdeps/unix/sysv/linux/ia64/register-dump.h
Normal file
@ -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)
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user