Refactor sigcontextinfo.h

This patch refactor sigcontextinfo.h header to use SA_SIGINFO as default
for both gmon and debug implementations.  This allows simplify
profil-counter.h on Linux to use a single implementation and remove the
requirements for newer ports to redefine __sigaction/sigaction to use
SA_SIGINFO.

The GET_PC macro is also replaced with a function sigcontext_get_pc that
returns an uintptr_t instead of a void pointer.  It allows easier convertion
to integer on ILP32 architecture, such as x32, without the need to suppress
compiler warnings.

The patch also requires some refactor of register-dump.h file for some
architectures (to reflect it is now called from a sa_sigaction instead of
sa_handler signal context).

   - Alpha, i386, and s390 are straighfoward to take in consideration the
     new argument type.

   - ia64 takes in consideration the kernel pass a struct sigcontextt
     as third argument for sa_sigaction.

   - sparc take in consideration the kernel pass a pt_regs struct
     as third argument for sa_sigaction.

   - m68k dummy function is removed and the FP state is dumped on
     register_dump itself.

   - For SH the register-dump.h file is consolidate on a common implementation
     and the floating-point state is checked based on ownedfp field.

The register_dump does not change its output format in any affected
architecture.

I checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, sparcv9-linux-gnu, sparc64-linux-gnu, powerpc-linux-gnu,
powerpc64-linux-gnu, and powerpc64le-linux-gnu.

I also checked the libSegFault.so through catchsegv on alpha-linux-gnu,
m68k-linux-gnu and sh4-linux-gnu to confirm the output has not changed.

	Adhemerval Zanella  <adhemerval.zanella@linaro.org>
	Florian Weimer  <fweimer@redhat.com>

	* debug/segfault.c (install_handler): Use SA_SIGINFO if defined.
	* sysdeps/generic/profil-counter.h (__profil_counter): Cast to
	uintptr_t.
	* sysdeps/generic/sigcontextinfo.h (GET_PC): Rename to
	sigcontext_get_pc and return aligned cast to uintptr_t.
	* sysdeps/mach/hurd/i386/sigcontextinfo.h (GET_PC): Likewise.
	* sysdeps/posix/profil.c (profil_count): Change PC argument to
	uintptr_t.
	(__profil): Use SA_SIGINFO.
	* sysdeps/posix/sprofil.c (profil_count): Change PCP argument to
	uintptr_t.
	(__sprofil): Use SA_SIGINFO.
	* sysdeps/unix/sysv/linux/profil-counter.h: New file.
	* sysdeps/unix/sysv/linux/aarch64/profil-counter.h: Remove file.
	* sysdeps/unix/sysv/linux/csky/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/i386/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/ia64/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/nios2/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/riscv/profil-counter.h: Likewise.
	* sysdeps/sysv/linux/s390/s390-32/profil-counter.h: Likewise.
	* sysdeps/sysv/linux/s390/s390-64/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/profil-counter.h: Likewise.
	* sysdeps/unix/sysv/linux/arm/profil-counter.h (__profil_counter):
	Assume SA_SIGINFO and use sigcontext_get_pc instead of GET_PC.
	* sysdeps/unix/sysv/linux/sparc/profil-counter.h: New file.
	* sysdeps/unix/sysv/linux/sparc/sparc64/profil-counter.h: Remove file.
	* sysdeps/unix/sysv/linux/sparc/sparc32/profil-counter.h: Likewise.
	* sysdpes/unix/sysv/linux/aarch64/sigcontextinfo.h (SIGCONTEXT,
	GET_PC, __sigaction, sigaction): Remove defines.
	(sigcontext_get_pc): New function.
	* sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/arm/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/csky/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/i386/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/s390/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/sigcontextinfo.h: Likewise.
	* sysdeps/sysv/linux/sparc/sparc32/sigcontextinfo.h: Likewise.
	* sysdeps/sysv/linux/sparc/sparc64/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h: Likewise.
	* sysdeps/unix/sysv/linux/alpha/register-dump.h (register_dump):
	Handle CTX argument as ucontext_t.
	* sysdeps/unix/sysv/linux/i386/register-dump.h: Likewise.
	Likewise.
	* sysdeps/unix/sysv/linux/m68k/register-dump.h: Likewise.
	* sysdeps/sysv/linux/s390/s390-32/register-dump.h: Likewise.
	* sysdeps/sysv/linux/s390/s390-64/register-dump.h: Likewise.
	* sysdeps/unix/sysv/linux/sh/register-dump.h: New file.
	* sysdeps/unix/sysv/linux/sh/sh4/register-dump.h: Remove File.
	* sysdeps/unix/sysv/linux/sh/sh3/register-dump.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/register-dump.h: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/register-dump.h: Likewise.
	* sysdeps/unix/sysv/linux/Makefile (tests-internal): Add
	tst-sigcontextinfo-get_pc.
	* sysdeps/unix/sysv/linux/tst-sigcontextinfo-get_pc.c: New file.
	(CFLAGS-tst-sigcontextinfo-get_pc.c): New rule.
This commit is contained in:
Adhemerval Zanella 2018-12-17 16:44:14 -02:00
parent 624c109b2a
commit a43565ac44
52 changed files with 955 additions and 954 deletions

View File

@ -1,3 +1,75 @@
2019-08-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
Florian Weimer <fweimer@redhat.com>
* debug/segfault.c (install_handler): Use SA_SIGINFO if defined.
* sysdeps/generic/profil-counter.h (__profil_counter): Cast to
uintptr_t.
* sysdeps/generic/sigcontextinfo.h (GET_PC): Rename to
sigcontext_get_pc and return aligned cast to uintptr_t.
* sysdeps/mach/hurd/i386/sigcontextinfo.h (GET_PC): Likewise.
* sysdeps/posix/profil.c (profil_count): Change PC argument to
uintptr_t.
(__profil): Use SA_SIGINFO.
* sysdeps/posix/sprofil.c (profil_count): Change PCP argument to
uintptr_t.
(__sprofil): Use SA_SIGINFO.
* sysdeps/unix/sysv/linux/profil-counter.h: New file.
* sysdeps/unix/sysv/linux/aarch64/profil-counter.h: Remove file.
* sysdeps/unix/sysv/linux/csky/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/i386/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/ia64/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/microblaze/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/mips/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/nios2/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/profil-counter.h: Likewise.
* sysdeps/sysv/linux/s390/s390-32/profil-counter.h: Likewise.
* sysdeps/sysv/linux/s390/s390-64/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/sh/profil-counter.h: Likewise.
* sysdeps/unix/sysv/linux/arm/profil-counter.h (__profil_counter):
Assume SA_SIGINFO and use sigcontext_get_pc instead of GET_PC.
* sysdeps/unix/sysv/linux/sparc/profil-counter.h: New file.
* sysdeps/unix/sysv/linux/sparc/sparc64/profil-counter.h: Remove file.
* sysdeps/unix/sysv/linux/sparc/sparc32/profil-counter.h: Likewise.
* sysdpes/unix/sysv/linux/aarch64/sigcontextinfo.h (SIGCONTEXT,
GET_PC, __sigaction, sigaction): Remove defines.
(sigcontext_get_pc): New function.
* sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/arm/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/csky/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/i386/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/ia64/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/m68k/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/mips/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/s390/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/riscv/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/sh/sigcontextinfo.h: Likewise.
* sysdeps/sysv/linux/sparc/sparc32/sigcontextinfo.h: Likewise.
* sysdeps/sysv/linux/sparc/sparc64/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h: Likewise.
* sysdeps/unix/sysv/linux/alpha/register-dump.h (register_dump):
Handle CTX argument as ucontext_t.
* sysdeps/unix/sysv/linux/i386/register-dump.h: Likewise.
Likewise.
* sysdeps/unix/sysv/linux/m68k/register-dump.h: Likewise.
* sysdeps/sysv/linux/s390/s390-32/register-dump.h: Likewise.
* sysdeps/sysv/linux/s390/s390-64/register-dump.h: Likewise.
* sysdeps/unix/sysv/linux/sh/register-dump.h: New file.
* sysdeps/unix/sysv/linux/sh/sh4/register-dump.h: Remove File.
* sysdeps/unix/sysv/linux/sh/sh3/register-dump.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc32/register-dump.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/register-dump.h: Likewise.
* sysdeps/unix/sysv/linux/Makefile (tests-internal): Add
tst-sigcontextinfo-get_pc.
* sysdeps/unix/sysv/linux/tst-sigcontextinfo-get_pc.c: New file.
(CFLAGS-tst-sigcontextinfo-get_pc.c): New rule.
2019-08-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/generic/single-thread.h (RTLD_SINGLE_THREAD_P): Add

View File

@ -35,6 +35,10 @@
passed up by the signal handler. */
#include <sigcontextinfo.h>
#ifdef SA_SIGINFO
# define SIGCONTEXT siginfo_t *info, void *
#endif
/* Get code to possibly dump the content of all registers. */
#include <register-dump.h>
@ -101,7 +105,7 @@ catch_segfault (int signal, SIGCONTEXT ctx)
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);
pc = sigcontext_get_pc (ctx);
for (i = 0; i < cnt; ++i)
if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16)
break;
@ -148,9 +152,15 @@ install_handler (void)
const char *sigs = getenv ("SEGFAULT_SIGNALS");
const char *name;
sa.sa_handler = (void *) catch_segfault;
#ifdef SA_SIGINFO
sa.sa_sigaction = catch_segfault;
sa.sa_flags = SA_SIGINFO;
#else
sa.sa_handler = (void*) catch_segfault;
sa.sa_flags = 0;
#endif
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_flags |= SA_RESTART;
/* Maybe we are expected to use an alternative stack. */
if (getenv ("SEGFAULT_USE_ALTSTACK") != 0)

View File

@ -22,5 +22,5 @@
static void
__profil_counter (int signr, int code, struct sigcontext *scp)
{
profil_count ((void *) scp->sc_pc);
profil_count ((uintptr_t) scp->sc_pc);
}

View File

@ -16,6 +16,15 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
/* In general we cannot provide any information. */
#define SIGCONTEXT struct sigcontext *
#define GET_PC(ctx) ((void *) 0)
static inline uintptr_t
sigcontext_get_pc (const struct sigcontext *ctx)
{
return 0;
}
#endif

View File

@ -15,5 +15,14 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#define SIGCONTEXT struct sigcontext
#define GET_PC(ctx) ((void *) (ctx).sc_eip)
static inline uintptr_t
sigcontext_get_pc (struct sigcontext ctx)
{
return ctx.sc_eip;
}
#endif

View File

@ -21,6 +21,7 @@
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <stdint.h>
#include <libc-internal.h>
#include <sigsetops.h>
@ -36,9 +37,9 @@ static size_t pc_offset;
static u_int pc_scale;
static inline void
profil_count (void *pc)
profil_count (uintptr_t pc)
{
size_t i = (pc - pc_offset - (void *) 0) / 2;
size_t i = (pc - pc_offset) / 2;
if (sizeof (unsigned long long int) > sizeof (size_t))
i = (unsigned long long int) i * pc_scale / 65536;
@ -104,8 +105,14 @@ __profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale)
pc_offset = offset;
pc_scale = scale;
act.sa_handler = (sighandler_t) &__profil_counter;
act.sa_flags = SA_RESTART;
#ifdef SA_SIGINFO
act.sa_sigaction = __profil_counter;
act.sa_flags = SA_SIGINFO;
#else
act.sa_handler = __profil_counter;
act.sa_flags = 0;
#endif
act.sa_flags |= SA_RESTART;
__sigfillset (&act.sa_mask);
if (__sigaction (SIGPROF, &act, oact_ptr) < 0)
return -1;

View File

@ -105,10 +105,10 @@ index_to_pc (unsigned long int n, size_t offset, unsigned int scale,
}
static void
profil_count (void *pcp, int prof_uint)
profil_count (uintptr_t pcp, int prof_uint)
{
struct region *region, *r = prof_info.last;
size_t lo, hi, mid, pc = (unsigned long int) pcp;
size_t lo, hi, mid, pc = pcp;
unsigned long int i;
/* Fast path: pc is in same region as before. */
@ -165,13 +165,13 @@ profil_count (void *pcp, int prof_uint)
}
static inline void
profil_count_ushort (void *pcp)
profil_count_ushort (uintptr_t pcp)
{
profil_count (pcp, 0);
}
static inline void
profil_count_uint (void *pcp)
profil_count_uint (uintptr_t pcp)
{
profil_count (pcp, 1);
}
@ -334,11 +334,18 @@ __sprofil (struct prof *profp, int profcnt, struct timeval *tvp,
prof_info.last = prof_info.region;
/* Install SIGPROF handler. */
if (flags & PROF_UINT)
act.sa_handler = (sighandler_t) &__profil_counter_uint;
else
act.sa_handler = (sighandler_t) &__profil_counter_ushort;
act.sa_flags = SA_RESTART;
#ifdef SA_SIGINFO
act.sa_sigaction= flags & PROF_UINT
? __profil_counter_uint
: __profil_counter_ushort;
act.sa_flags = SA_SIGINFO;
#else
act.sa_handler = flags & PROF_UINT
? (sighandler_t) __profil_counter_uint
: (sighandler_t) __profil_counter_ushort;
act.sa_flags = 0;
#endif
act.sa_flags |= SA_RESTART;
__sigfillset (&act.sa_mask);
if (__sigaction (SIGPROF, &act, &prof_info.saved_action) < 0)
return -1;

View File

@ -55,7 +55,9 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
tst-tgkill
tests-internal += tst-ofdlocks-compat
tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
CFLAGS-tst-sigcontextinfo-get_pc.c = -fasynchronous-unwind-tables
# Generate the list of SYS_* macros for the system calls (__NR_*
# macros). The file syscall-names.list contains all possible system

View File

@ -1,20 +0,0 @@
/* Copyright (C) 2009-2019 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 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, see
<http://www.gnu.org/licenses/>. */
/* We can use the ix86 version. */
#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>

View File

@ -16,20 +16,16 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <stdint.h>
#include <sys/ucontext.h>
#define SIGCONTEXT siginfo_t *_si, ucontext_t *
#define GET_PC(ctx) ((void *) (uintptr_t) (ctx)->uc_mcontext.pc)
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.pc;
}
/* There is no reliable way to get the sigcontext unless we use a
three-argument signal handler. */
#define __sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(__sigaction) (sig, act, oact); \
})
#define sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(sigaction) (sig, act, oact); \
})
#endif

View File

@ -16,8 +16,10 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <string.h>
#include <ucontext.h>
#include <sys/uio.h>
#include <_itoa.h>
/* We will print the register dump in this format:
@ -48,109 +50,190 @@
TA0: XXXXXXXXXXXXXXXX TA1: XXXXXXXXXXXXXXXX TA2: XXXXXXXXXXXXXXXX
*/
#define NREGS (32+32+3)
static const char __attribute__((aligned(8))) regnames[NREGS][8] =
static void
hexvalue (unsigned long int value, char *buf, size_t len)
{
" V0: ", " T0: ", " T1: ",
" T2: ", " T3: ", " T4: ",
" T5: ", " T6: ", " T7: ",
" S0: ", " S1: ", " S2: ",
" S3: ", " S4: ", " S5: ",
" S6: ", " A0: ", " A1: ",
" A2: ", " A3: ", " A4: ",
" A5: ", " T8: ", " T9: ",
" T10: ", " T11: ", " RA: ",
" T12: ", " AT: ", " GP: ",
" SP: ", " PC: ",
" FP0: ", " FP1: ", " FP2: ",
" FP3: ", " FP4: ", " FP5: ",
" FP6: ", " FP7: ", " FP8: ",
" FP9: ", " FP10: ", " FP11: ",
" FP12: ", " FP13: ", " FP14: ",
" FP15: ", " FP16: ", " FP17: ",
" FP18: ", " FP19: ", " FP20: ",
" FP21: ", " FP22: ", " FP23: ",
" FP24: ", " FP25: ", " FP26: ",
" FP27: ", " FP28: ", " FP29: ",
" FP30: ", " FPCR: ",
" TA0: ", " TA1: ", " TA2: "
};
#define O(FIELD, LF) offsetof(struct sigcontext, FIELD) + LF
static const int offsets[NREGS] =
{
O(sc_regs[0], 0), O(sc_regs[1], 0), O(sc_regs[2], 1),
O(sc_regs[3], 0), O(sc_regs[4], 0), O(sc_regs[5], 1),
O(sc_regs[6], 0), O(sc_regs[7], 0), O(sc_regs[8], 1),
O(sc_regs[9], 0), O(sc_regs[10], 0), O(sc_regs[11], 1),
O(sc_regs[12], 0), O(sc_regs[13], 0), O(sc_regs[14], 1),
O(sc_regs[15], 0), O(sc_regs[16], 0), O(sc_regs[17], 1),
O(sc_regs[18], 0), O(sc_regs[19], 0), O(sc_regs[20], 1),
O(sc_regs[21], 0), O(sc_regs[22], 0), O(sc_regs[23], 1),
O(sc_regs[24], 0), O(sc_regs[25], 0), O(sc_regs[26], 1),
O(sc_regs[27], 0), O(sc_regs[28], 0), O(sc_regs[29], 1),
O(sc_regs[30], 0), O(sc_pc, 2),
O(sc_fpregs[0], 0), O(sc_fpregs[1], 0), O(sc_fpregs[2], 1),
O(sc_fpregs[3], 0), O(sc_fpregs[4], 0), O(sc_fpregs[5], 1),
O(sc_fpregs[6], 0), O(sc_fpregs[7], 0), O(sc_fpregs[8], 1),
O(sc_fpregs[9], 0), O(sc_fpregs[10], 0), O(sc_fpregs[11], 1),
O(sc_fpregs[12], 0), O(sc_fpregs[13], 0), O(sc_fpregs[14], 1),
O(sc_fpregs[15], 0), O(sc_fpregs[16], 0), O(sc_fpregs[17], 1),
O(sc_fpregs[18], 0), O(sc_fpregs[19], 0), O(sc_fpregs[20], 1),
O(sc_fpregs[21], 0), O(sc_fpregs[22], 0), O(sc_fpregs[23], 1),
O(sc_fpregs[24], 0), O(sc_fpregs[25], 0), O(sc_fpregs[26], 1),
O(sc_fpregs[27], 0), O(sc_fpregs[28], 0), O(sc_fpregs[29], 1),
O(sc_fpregs[30], 0), O(sc_fpcr, 2),
O(sc_traparg_a0, 0), O(sc_traparg_a1, 0), O(sc_traparg_a2, 1)
};
#undef O
char *cp = _itoa_word (value, buf + len, 16, 0);
while (cp > buf)
*--cp = '0';
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char buf[NREGS*(8+16) + 25 + 80];
char *p = buf;
size_t i;
struct iovec iov[31 * 2 + 2 /* REGS + PC. */
+ 31 * 2 + 2 /* FREGS + FPCR. */
+ (3 * 2) /* TA0, TA1, TA3. */
+ 1 /* '\n'. */];
size_t nr = 0;
p = stpcpy (p, "Register dump:\n\n");
#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
for (i = 0; i < NREGS; ++i)
{
int this_offset, this_lf;
unsigned long val;
signed long j;
char regs[31][16];
char pc[16];
for (int i = 0; i < 31; i++)
hexvalue (ctx->uc_mcontext.sc_regs[i], regs[i], 16);
hexvalue (ctx->uc_mcontext.sc_pc, pc, 16);
this_offset = offsets[i];
this_lf = this_offset & 7;
/* Generate the output. */
ADD_STRING ("Register dump:\n\n V0: ");
ADD_MEM (regs[0], 16);
ADD_STRING (" T0: ");
ADD_MEM (regs[1], 16);
ADD_STRING (" T1: ");
ADD_MEM (regs[2], 16);
ADD_STRING ("\n T2: ");
ADD_MEM (regs[3], 16);
ADD_STRING (" T3: ");
ADD_MEM (regs[4], 16);
ADD_STRING (" T4: ");
ADD_MEM (regs[5], 16);
ADD_STRING ("\n T5: ");
ADD_MEM (regs[6], 16);
ADD_STRING (" T6: ");
ADD_MEM (regs[7], 16);
ADD_STRING (" T7: ");
ADD_MEM (regs[8], 16);
ADD_STRING ("\n S0: ");
ADD_MEM (regs[9], 16);
ADD_STRING (" S1: ");
ADD_MEM (regs[10], 16);
ADD_STRING (" S2: ");
ADD_MEM (regs[11], 16);
ADD_STRING ("\n S3: ");
ADD_MEM (regs[12], 16);
ADD_STRING (" S4: ");
ADD_MEM (regs[13], 16);
ADD_STRING (" S5: ");
ADD_MEM (regs[14], 16);
ADD_STRING ("\n S6: ");
ADD_MEM (regs[15], 16);
ADD_STRING (" A0: ");
ADD_MEM (regs[16], 16);
ADD_STRING (" A1: ");
ADD_MEM (regs[17], 16);
ADD_STRING ("\n A2: ");
ADD_MEM (regs[18], 16);
ADD_STRING (" A3: ");
ADD_MEM (regs[19], 16);
ADD_STRING (" A4: ");
ADD_MEM (regs[20], 16);
ADD_STRING ("\n A5: ");
ADD_MEM (regs[21], 16);
ADD_STRING (" T8: ");
ADD_MEM (regs[22], 16);
ADD_STRING (" T9: ");
ADD_MEM (regs[23], 16);
ADD_STRING ("\n T10: ");
ADD_MEM (regs[24], 16);
ADD_STRING (" T11: ");
ADD_MEM (regs[25], 16);
ADD_STRING (" RA: ");
ADD_MEM (regs[26], 16);
ADD_STRING ("\n T12: ");
ADD_MEM (regs[27], 16);
ADD_STRING (" AT: ");
ADD_MEM (regs[28], 16);
ADD_STRING (" GP: ");
ADD_MEM (regs[29], 16);
ADD_STRING ("\n SP: ");
ADD_MEM (regs[30], 16);
ADD_STRING (" PC: ");
ADD_MEM (pc, 16);
val = *(unsigned long *)(((size_t)ctx + this_offset) & -8);
char fpregs[31][16];
char fpcr[16];
for (int i = 0; i < 31; i++)
hexvalue (ctx->uc_mcontext.sc_fpregs[i], fpregs[i], 16);
hexvalue (ctx->uc_mcontext.sc_fpcr, fpcr, 16);
memcpy (p, regnames[i], 8);
p += 8;
ADD_STRING ("\n\n FP0: ");
ADD_MEM (fpregs[0], 16);
ADD_STRING (" FP1: ");
ADD_MEM (fpregs[1], 16);
ADD_STRING (" FP2: ");
ADD_MEM (fpregs[2], 16);
ADD_STRING ("\n FP3: ");
ADD_MEM (fpregs[3], 16);
ADD_STRING (" FP4: ");
ADD_MEM (fpregs[4], 16);
ADD_STRING (" FP5: ");
ADD_MEM (fpregs[5], 16);
ADD_STRING ("\n FP6: ");
ADD_MEM (fpregs[6], 16);
ADD_STRING (" FP7: ");
ADD_MEM (fpregs[7], 16);
ADD_STRING (" FP8: ");
ADD_MEM (fpregs[8], 16);
ADD_STRING ("\n FP9: ");
ADD_MEM (fpregs[9], 16);
ADD_STRING (" FP10: ");
ADD_MEM (fpregs[10], 16);
ADD_STRING (" FP11: ");
ADD_MEM (fpregs[11], 16);
ADD_STRING ("\n FP12: ");
ADD_MEM (fpregs[12], 16);
ADD_STRING (" FP13: ");
ADD_MEM (fpregs[13], 16);
ADD_STRING (" FP14: ");
ADD_MEM (fpregs[14], 16);
ADD_STRING ("\n FP15: ");
ADD_MEM (fpregs[15], 16);
ADD_STRING (" FP16: ");
ADD_MEM (fpregs[16], 16);
ADD_STRING (" FP17: ");
ADD_MEM (fpregs[17], 16);
ADD_STRING ("\n FP18: ");
ADD_MEM (fpregs[18], 16);
ADD_STRING (" FP19: ");
ADD_MEM (fpregs[19], 16);
ADD_STRING (" FP20: ");
ADD_MEM (fpregs[20], 16);
ADD_STRING ("\n FP21: ");
ADD_MEM (fpregs[21], 16);
ADD_STRING (" FP22: ");
ADD_MEM (fpregs[22], 16);
ADD_STRING (" FP23: ");
ADD_MEM (fpregs[23], 16);
ADD_STRING ("\n FP24: ");
ADD_MEM (fpregs[24], 16);
ADD_STRING (" FP25: ");
ADD_MEM (fpregs[25], 16);
ADD_STRING (" FP26: ");
ADD_MEM (fpregs[26], 16);
ADD_STRING ("\n FP27: ");
ADD_MEM (fpregs[27], 16);
ADD_STRING (" FP28: ");
ADD_MEM (fpregs[28], 16);
ADD_STRING (" FP29: ");
ADD_MEM (fpregs[29], 16);
ADD_STRING ("\n FP30: ");
ADD_MEM (fpregs[30], 16);
ADD_STRING (" FPCR: ");
ADD_MEM (fpcr, 16);
for (j = 60; j >= 0; j -= 4)
{
unsigned long x = (val >> j) & 15;
x += x < 10 ? '0' : 'a' - 10;
*p++ = x;
}
char traparg[3][16];
hexvalue (ctx->uc_mcontext.sc_traparg_a0, traparg[0], 16);
hexvalue (ctx->uc_mcontext.sc_traparg_a1, traparg[1], 16);
hexvalue (ctx->uc_mcontext.sc_traparg_a2, traparg[2], 16);
ADD_STRING ("\n\n TA0: ");
ADD_MEM (traparg[0], 16);
ADD_STRING (" TA1: ");
ADD_MEM (traparg[1], 16);
ADD_STRING (" TA2: ");
ADD_MEM (traparg[2], 16);
if (this_lf > 0)
{
if (this_lf > 1)
*p++ = '\n';
*p++ = '\n';
}
}
ADD_STRING ("\n");
write (fd, buf, p - buf);
/* Write the stuff out. */
writev (fd, iov, nr);
}
#define REGISTER_DUMP register_dump (fd, ctx)

View File

@ -15,5 +15,16 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT int _code, struct sigcontext *
#define GET_PC(ctx) ((void *) (ctx)->sc_pc)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <stdint.h>
#include <sys/ucontext.h>
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.sc_pc;
}
#endif

View File

@ -20,9 +20,9 @@
#include <sigcontextinfo.h>
void
__profil_counter (int signo, const SIGCONTEXT scp)
__profil_counter (int signo, siginfo_t *_si, void *scp)
{
profil_count ((void *) GET_PC (scp));
profil_count (sigcontext_get_pc (scp));
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite

View File

@ -16,24 +16,13 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#include <sys/ucontext.h>
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#define SIGCONTEXT siginfo_t *_si, ucontext_t *
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.arm_pc;
}
/* The sigcontext structure changed between 2.0 and 2.1 kernels. On any
modern system we should be able to assume that the "new" format will be
in use. */
#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.arm_pc)
/* There is no reliable way to get the sigcontext unless we use a
three-argument signal handler. */
#define __sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(__sigaction) (sig, act, oact); \
})
#define sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(sigaction) (sig, act, oact); \
})
#endif

View File

@ -1,31 +0,0 @@
/* Low-level statistical profiling support function. Linux/C-SKY version.
Copyright (C) 2018-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sigcontextinfo.h>
void
__profil_counter (int signo, const SIGCONTEXT scp)
{
profil_count ((void *) GET_PC (scp));
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite
the signal context. */
asm volatile ("");
}

View File

@ -16,17 +16,13 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT siginfo_t *_si, struct ucontext_t *
#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.__gregs.__pc)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
/* There is no reliable way to get the sigcontext unless we use a
three-argument signal handler. */
#define __sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(__sigaction) (sig, act, oact); \
})
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.__gregs.__pc;
}
#define sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(sigaction) (sig, act, oact); \
})
#endif

View File

@ -1,5 +1,5 @@
/* Machine-dependent SIGPROF signal handler. PA-RISC version
Copyright (C) 1996-2019 Free Software Foundation, Inc.
Copyright (C) 2019 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
@ -16,9 +16,15 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
static void
__profil_counter (int signr, siginfo_t *si, ucontext_t *uctx)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <sys/ucontext.h>
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
unsigned long ip = uctx->uc_mcontext.sc_iaoq[0] & ~0x3;
profil_count ((void *) ip);
return ctx->uc_mcontext.sc_iaoq[0] & ~0x3;
}
#endif

View File

@ -1,31 +0,0 @@
/* Low-level statistical profiling support function. Linux/i386 version.
Copyright (C) 1996-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sigcontextinfo.h>
static void
__profil_counter (int signo, const SIGCONTEXT scp)
{
profil_count ((void *) GET_PC (scp));
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite
the signal context. */
asm volatile ("");
}

View File

@ -51,7 +51,7 @@ hexvalue (unsigned long int value, char *buf, size_t len)
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char regs[21][8];
char fpregs[31][8];
@ -68,27 +68,27 @@ register_dump (int fd, struct sigcontext *ctx)
++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);
hexvalue (ctx->uc_mcontext.gregs[REG_EAX], regs[0], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_EBX], regs[1], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_ECX], regs[2], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_EDX], regs[3], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_ESI], regs[4], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_EDI], regs[5], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_EBP], regs[6], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_ESP], regs[7], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_EIP], regs[8], 8);
hexvalue (ctx->uc_flags, regs[9], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_CS], regs[10], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_DS], regs[11], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_ES], regs[12], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_FS], regs[13], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_GS], regs[14], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_SS], regs[15], 4);
hexvalue (ctx->uc_mcontext.gregs[REG_TRAPNO], regs[16], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_ERR], regs[17], 8);
hexvalue (ctx->uc_mcontext.oldmask, regs[18], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_UESP], regs[19], 8);
hexvalue (ctx->uc_mcontext.cr2, regs[20], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n EAX: ");
@ -134,116 +134,112 @@ register_dump (int fd, struct sigcontext *ctx)
ADD_STRING (" CR2: ");
ADD_MEM (regs[20], 8);
if (ctx->fpstate != NULL)
{
/* Generate output for the FPU control/status registers. */
hexvalue (ctx->__fpregs_mem.cw, fpregs[0], 8);
hexvalue (ctx->__fpregs_mem.sw, fpregs[1], 8);
hexvalue (ctx->__fpregs_mem.tag, fpregs[2], 8);
hexvalue (ctx->__fpregs_mem.ipoff, fpregs[3], 8);
hexvalue (ctx->__fpregs_mem.cssel, fpregs[4], 4);
hexvalue (ctx->__fpregs_mem.dataoff, fpregs[5], 8);
hexvalue (ctx->__fpregs_mem.datasel, fpregs[6], 4);
/* 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);
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->__fpregs_mem._st[0].exponent, fpregs[7], 8);
hexvalue (ctx->__fpregs_mem._st[0].significand[3] << 16
| ctx->__fpregs_mem._st[0].significand[2], fpregs[8], 8);
hexvalue (ctx->__fpregs_mem._st[0].significand[1] << 16
| ctx->__fpregs_mem._st[0].significand[0], fpregs[9], 8);
hexvalue (ctx->__fpregs_mem._st[1].exponent, fpregs[10], 8);
hexvalue (ctx->__fpregs_mem._st[1].significand[3] << 16
| ctx->__fpregs_mem._st[1].significand[2], fpregs[11], 8);
hexvalue (ctx->__fpregs_mem._st[1].significand[1] << 16
| ctx->__fpregs_mem._st[1].significand[0], fpregs[12], 8);
hexvalue (ctx->__fpregs_mem._st[2].exponent, fpregs[13], 8);
hexvalue (ctx->__fpregs_mem._st[2].significand[3] << 16
| ctx->__fpregs_mem._st[2].significand[2], fpregs[14], 8);
hexvalue (ctx->__fpregs_mem._st[2].significand[1] << 16
| ctx->__fpregs_mem._st[2].significand[0], fpregs[15], 8);
hexvalue (ctx->__fpregs_mem._st[3].exponent, fpregs[16], 8);
hexvalue (ctx->__fpregs_mem._st[3].significand[3] << 16
| ctx->__fpregs_mem._st[3].significand[2], fpregs[17], 8);
hexvalue (ctx->__fpregs_mem._st[3].significand[1] << 16
| ctx->__fpregs_mem._st[3].significand[0], fpregs[18], 8);
hexvalue (ctx->__fpregs_mem._st[4].exponent, fpregs[19], 8);
hexvalue (ctx->__fpregs_mem._st[4].significand[3] << 16
| ctx->__fpregs_mem._st[4].significand[2], fpregs[20], 8);
hexvalue (ctx->__fpregs_mem._st[4].significand[1] << 16
| ctx->__fpregs_mem._st[4].significand[0], fpregs[21], 8);
hexvalue (ctx->__fpregs_mem._st[5].exponent, fpregs[22], 8);
hexvalue (ctx->__fpregs_mem._st[5].significand[3] << 16
| ctx->__fpregs_mem._st[5].significand[2], fpregs[23], 8);
hexvalue (ctx->__fpregs_mem._st[5].significand[1] << 16
| ctx->__fpregs_mem._st[5].significand[0], fpregs[24], 8);
hexvalue (ctx->__fpregs_mem._st[6].exponent, fpregs[25], 8);
hexvalue (ctx->__fpregs_mem._st[6].significand[3] << 16
| ctx->__fpregs_mem._st[6].significand[2], fpregs[26], 8);
hexvalue (ctx->__fpregs_mem._st[6].significand[1] << 16
| ctx->__fpregs_mem._st[6].significand[0], fpregs[27], 8);
hexvalue (ctx->__fpregs_mem._st[7].exponent, fpregs[28], 8);
hexvalue (ctx->__fpregs_mem._st[7].significand[3] << 16
| ctx->__fpregs_mem._st[7].significand[2], fpregs[29], 8);
hexvalue (ctx->__fpregs_mem._st[7].significand[1] << 16
| ctx->__fpregs_mem._st[7].significand[0], fpregs[30], 8);
/* 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\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");
@ -252,4 +248,4 @@ register_dump (int fd, struct sigcontext *ctx)
}
#define REGISTER_DUMP register_dump (fd, &ctx)
#define REGISTER_DUMP register_dump (fd, ctx)

View File

@ -16,5 +16,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT struct sigcontext
#define GET_PC(ctx) ((void *) ctx.eip)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.gregs[REG_EIP];
}
#endif

View File

@ -1,31 +0,0 @@
/* Machine-dependent SIGPROF signal handler. IA-64 version.
Copyright (C) 1996-2019 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 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, see
<http://www.gnu.org/licenses/>. */
/* In many Unix systems signal handlers are called like this
and the interrupted PC is easily findable in the `struct sigcontext'. */
static void
__profil_counter (int signr, siginfo_t *si, struct sigcontext *scp)
{
unsigned long ip = scp->sc_ip & ~0X3ULL, slot = scp->sc_ip & 0x3ull;
/* Note: Linux/ia64 encodes the slot number in bits 0 and 1. We
want to multiply the slot number by four so we can use bins of
width 4 to get accurate instruction-level profiling. */
profil_count ((void *) (ip + 4*slot));
}

View File

@ -15,5 +15,15 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT siginfo_t *_si, struct sigcontext *
#define GET_PC(ctx) ((ctx)->sc_ip)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
/* Unlike other architectures, ia64 passes 'struct sigcontext' pointer as
the third argument to a sa_sigaction handler with SA_SIGINFO enabled. */
static inline uintptr_t
sigcontext_get_pc (const struct sigcontext *ctx)
{
return ctx->sc_ip;
}
#endif

View File

@ -39,35 +39,9 @@
*/
/* Linux saves only the call-clobbered registers in the sigcontext. We
need to use a trampoline that saves the rest so that the C code can
access them. We use the sc_fpstate field, since the handler is not
supposed to return anyway, thus it doesn't matter that it's clobbered. */
/* static */ void catch_segfault (int, int, struct sigcontext *);
/* Dummy function so that we can use asm with arguments. */
static void __attribute_used__
__dummy__ (void)
{
asm ("\n\
catch_segfault:\n\
move.l 12(%%sp),%%a0\n\
lea %c0(%%a0),%%a0\n\
/* Clear the first 4 bytes to make it a null fp state, just\n\
in case the handler does return. */\n\
clr.l (%%a0)+\n\
movem.l %%d2-%%d7/%%a2-%%a6,(%%a0)\n"
#ifndef __mcoldfire__
"fmovem.x %%fp2-%%fp7,11*4(%%a0)\n"
#elif defined __mcffpu__
"fmovem.d %%fp2-%%fp7,11*4(%%a0)\n"
#endif
"jra real_catch_segfault"
: : "n" (offsetof (struct sigcontext, sc_fpstate)));
}
#define catch_segfault(a,b) \
__attribute_used__ real_catch_segfault(a,b)
#define FPCONTEXT_SIZE 216
#define uc_formatvec __glibc_reserved1[FPCONTEXT_SIZE/4]
#define uc_oldmask uc_sigmask.__val[0]
static void
hexvalue (unsigned long int value, char *buf, size_t len)
@ -78,13 +52,11 @@ hexvalue (unsigned long int value, char *buf, size_t len)
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char regs[20][8];
char fpregs[11][24];
struct iovec iov[63], *next_iov = iov;
unsigned long *p = (unsigned long *) ctx->sc_fpstate + 1;
unsigned long *pfp = (unsigned long *) ctx->sc_fpregs;
int i, j, fpreg_size;
#define ADD_STRING(str) \
@ -103,35 +75,33 @@ register_dump (int fd, struct sigcontext *ctx)
#endif
/* Generate strings of register contents. */
hexvalue (ctx->sc_d0, regs[0], 8);
hexvalue (ctx->sc_d1, regs[1], 8);
hexvalue (*p++, regs[2], 8);
hexvalue (*p++, regs[3], 8);
hexvalue (*p++, regs[4], 8);
hexvalue (*p++, regs[5], 8);
hexvalue (*p++, regs[6], 8);
hexvalue (*p++, regs[7], 8);
hexvalue (ctx->sc_a0, regs[8], 8);
hexvalue (ctx->sc_a1, regs[9], 8);
hexvalue (*p++, regs[10], 8);
hexvalue (*p++, regs[11], 8);
hexvalue (*p++, regs[12], 8);
hexvalue (*p++, regs[13], 8);
hexvalue (*p++, regs[14], 8);
hexvalue (ctx->sc_usp, regs[15], 8);
hexvalue (ctx->sc_pc, regs[16], 8);
hexvalue (ctx->sc_sr, regs[17], 4);
hexvalue (ctx->sc_mask, regs[18], 8);
hexvalue (ctx->sc_formatvec & 0xfff, regs[19], 4);
for (i = 0; i < 2; i++)
hexvalue (ctx->uc_mcontext.gregs[R_D0], regs[0], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D1], regs[1], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D2], regs[2], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D3], regs[3], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D4], regs[4], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D5], regs[5], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D6], regs[6], 8);
hexvalue (ctx->uc_mcontext.gregs[R_D7], regs[7], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A0], regs[8], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A1], regs[9], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A2], regs[10], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A3], regs[11], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A4], regs[12], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A5], regs[13], 8);
hexvalue (ctx->uc_mcontext.gregs[R_A6], regs[14], 8);
hexvalue (ctx->uc_mcontext.gregs[R_SP], regs[15], 8);
hexvalue (ctx->uc_mcontext.gregs[R_PC], regs[16], 8);
hexvalue (ctx->uc_mcontext.gregs[R_PS], regs[17], 4);
hexvalue (ctx->uc_oldmask, regs[18], 8);
hexvalue (ctx->uc_formatvec & 0xfff, regs[19], 4);
for (i = 0; i < 8; i++)
for (j = 0; j < fpreg_size; j += 8)
hexvalue (*pfp++, fpregs[i] + j, 8);
for (i = 2; i < 8; i++)
for (j = 0; j < fpreg_size; j += 8)
hexvalue (*p++, fpregs[i] + j, 8);
hexvalue (ctx->sc_fpcntl[0], fpregs[8], 8);
hexvalue (ctx->sc_fpcntl[1], fpregs[9], 8);
hexvalue (ctx->sc_fpcntl[2], fpregs[10], 8);
hexvalue (ctx->uc_mcontext.fpregs.f_fpregs[i][j/8], fpregs[i] + j, 8);
hexvalue (ctx->uc_mcontext.fpregs.f_pcr, fpregs[8], 8);
hexvalue (ctx->uc_mcontext.fpregs.f_psr, fpregs[9], 8);
hexvalue (ctx->uc_mcontext.fpregs.f_fpiaddr, fpregs[10], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n D0: ");

View File

@ -16,5 +16,13 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT int _code, struct sigcontext *
#define GET_PC(ctx) ((void *) (ctx)->sc_pc)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.gregs[R_PC];
}
#endif

View File

@ -1,2 +0,0 @@
/* We can use the ix86 version. */
#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>

View File

@ -16,5 +16,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT int _code, ucontext_t *
#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.regs.pc)
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.regs.pc;
}
#endif

View File

@ -1,2 +0,0 @@
/* We can use the ix86 version. */
#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>

View File

@ -16,17 +16,13 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <sgidefs.h>
#if _MIPS_SIM == _ABIO32
#define SIGCONTEXT unsigned long _code, struct sigcontext *
#define GET_PC(ctx) ((void *) (unsigned long) ctx->sc_pc)
#else
#define SIGCONTEXT unsigned long _code, ucontext_t *
#define GET_PC(ctx) ((void *) (unsigned long) ctx->uc_mcontext.pc)
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.pc;
}
#endif

View File

@ -1,2 +0,0 @@
/* We can use the ix86 version. */
#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>

View File

@ -16,20 +16,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <sys/ucontext.h>
#include "kernel-features.h"
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#define SIGCONTEXT siginfo_t *_si, ucontext_t *
#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.regs[27])
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.regs[27];
}
/* There is no reliable way to get the sigcontext unless we use a
three-argument signal handler. */
#define __sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(__sigaction) (sig, act, oact); \
})
#define sigaction(sig, act, oact) ({ \
(act)->sa_flags |= SA_SIGINFO; \
(sigaction) (sig, act, oact); \
})
#endif

View File

@ -1,2 +0,0 @@
/* We can use the ix86 version. */
#include <sysdeps/unix/sysv/linux/i386/profil-counter.h>

View File

@ -15,7 +15,19 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <signal.h>
#define SIGCONTEXT struct sigcontext *
#define GET_PC(ctx) ((void *)((ctx)->regs->nip))
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
#ifdef __powerpc64__
return ctx->uc_mcontext.gp_regs[PT_NIP];
#else
return ctx->uc_mcontext.uc_regs->gregs[PT_NIP];
#endif
}
#endif

View File

@ -1,11 +1,11 @@
/* Low-level statistical profiling support function. Linux/x86-64 version.
/* Low-level statistical profiling support function. Linux version.
Copyright (C) 2001-2019 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 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.
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
@ -19,10 +19,11 @@
#include <signal.h>
#include <sigcontextinfo.h>
/* sa_sigaction signature to use along SA_SIGINFO. */
static void
__profil_counter (int signo, SIGCONTEXT scp)
__profil_counter (int signo, siginfo_t *info, void *ctx)
{
profil_count ((void *) GET_PC (scp));
profil_count (sigcontext_get_pc (ctx));
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite

View File

@ -1,31 +0,0 @@
/* Low-level statistical profiling support function. Linux/RISC-V version.
Copyright (C) 1996-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sigcontextinfo.h>
static void
__profil_counter (int signo, const SIGCONTEXT scp)
{
profil_count ((void *) GET_PC (scp));
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite
the signal context. */
asm volatile ("");
}

View File

@ -16,7 +16,15 @@
License along with the GNU C Library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <sys/ucontext.h>
#define SIGCONTEXT siginfo_t *_si, ucontext_t *
#define GET_PC(ctx) ((void *) ctx->uc_mcontext.__gregs[REG_PC])
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.__gregs[REG_PC];
}
#endif

View File

@ -1,26 +0,0 @@
/* Low-level statistical profiling support function. Linux/s390 version.
Copyright (C) 2000-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sigcontextinfo.h>
static void
__profil_counter (int signo, SIGCONTEXT scp)
{
profil_count((void *) ((unsigned long) GET_PC (scp) & 0x7fffffffUL));
}

View File

@ -45,7 +45,7 @@ hexvalue (unsigned long int value, char *buf, size_t len)
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char regs[19][8];
struct iovec iov[40];
@ -61,24 +61,24 @@ register_dump (int fd, struct sigcontext *ctx)
++nr
/* Generate strings of register contents. */
hexvalue (ctx->sregs->regs.gprs[0], regs[0], 8);
hexvalue (ctx->sregs->regs.gprs[1], regs[1], 8);
hexvalue (ctx->sregs->regs.gprs[2], regs[2], 8);
hexvalue (ctx->sregs->regs.gprs[3], regs[3], 8);
hexvalue (ctx->sregs->regs.gprs[4], regs[4], 8);
hexvalue (ctx->sregs->regs.gprs[5], regs[5], 8);
hexvalue (ctx->sregs->regs.gprs[6], regs[6], 8);
hexvalue (ctx->sregs->regs.gprs[7], regs[7], 8);
hexvalue (ctx->sregs->regs.gprs[8], regs[8], 8);
hexvalue (ctx->sregs->regs.gprs[9], regs[9], 8);
hexvalue (ctx->sregs->regs.gprs[10], regs[10], 8);
hexvalue (ctx->sregs->regs.gprs[11], regs[11], 8);
hexvalue (ctx->sregs->regs.gprs[12], regs[12], 8);
hexvalue (ctx->sregs->regs.gprs[13], regs[13], 8);
hexvalue (ctx->sregs->regs.gprs[14], regs[14], 8);
hexvalue (ctx->sregs->regs.gprs[15], regs[15], 8);
hexvalue (ctx->sregs->regs.psw.mask, regs[16], 8);
hexvalue (ctx->sregs->regs.psw.addr, regs[17], 8);
hexvalue (ctx->uc_mcontext.gregs[0], regs[0], 8);
hexvalue (ctx->uc_mcontext.gregs[1], regs[1], 8);
hexvalue (ctx->uc_mcontext.gregs[2], regs[2], 8);
hexvalue (ctx->uc_mcontext.gregs[3], regs[3], 8);
hexvalue (ctx->uc_mcontext.gregs[4], regs[4], 8);
hexvalue (ctx->uc_mcontext.gregs[5], regs[5], 8);
hexvalue (ctx->uc_mcontext.gregs[6], regs[6], 8);
hexvalue (ctx->uc_mcontext.gregs[7], regs[7], 8);
hexvalue (ctx->uc_mcontext.gregs[8], regs[8], 8);
hexvalue (ctx->uc_mcontext.gregs[9], regs[9], 8);
hexvalue (ctx->uc_mcontext.gregs[10], regs[10], 8);
hexvalue (ctx->uc_mcontext.gregs[11], regs[11], 8);
hexvalue (ctx->uc_mcontext.gregs[12], regs[12], 8);
hexvalue (ctx->uc_mcontext.gregs[13], regs[13], 8);
hexvalue (ctx->uc_mcontext.gregs[14], regs[14], 8);
hexvalue (ctx->uc_mcontext.gregs[15], regs[15], 8);
hexvalue (ctx->uc_mcontext.psw.mask, regs[16], 8);
hexvalue (ctx->uc_mcontext.psw.addr, regs[17], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n GPR0: ");

View File

@ -1,26 +0,0 @@
/* Low-level statistical profiling support function. Linux/s390 version.
Copyright (C) 2000-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sigcontextinfo.h>
static void
__profil_counter (int signo, SIGCONTEXT scp)
{
profil_count ((void *) GET_PC (scp));
}

View File

@ -48,7 +48,7 @@ hexvalue (unsigned long int value, char *buf, size_t len)
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char regs[19][16];
struct iovec iov[40];
@ -64,24 +64,24 @@ register_dump (int fd, struct sigcontext *ctx)
++nr
/* Generate strings of register contents. */
hexvalue (ctx->sregs->regs.gprs[0], regs[0], 16);
hexvalue (ctx->sregs->regs.gprs[1], regs[1], 16);
hexvalue (ctx->sregs->regs.gprs[2], regs[2], 16);
hexvalue (ctx->sregs->regs.gprs[3], regs[3], 16);
hexvalue (ctx->sregs->regs.gprs[4], regs[4], 16);
hexvalue (ctx->sregs->regs.gprs[5], regs[5], 16);
hexvalue (ctx->sregs->regs.gprs[6], regs[6], 16);
hexvalue (ctx->sregs->regs.gprs[7], regs[7], 16);
hexvalue (ctx->sregs->regs.gprs[8], regs[8], 16);
hexvalue (ctx->sregs->regs.gprs[9], regs[9], 16);
hexvalue (ctx->sregs->regs.gprs[10], regs[10], 16);
hexvalue (ctx->sregs->regs.gprs[11], regs[11], 16);
hexvalue (ctx->sregs->regs.gprs[12], regs[12], 16);
hexvalue (ctx->sregs->regs.gprs[13], regs[13], 16);
hexvalue (ctx->sregs->regs.gprs[14], regs[14], 16);
hexvalue (ctx->sregs->regs.gprs[15], regs[15], 16);
hexvalue (ctx->sregs->regs.psw.mask, regs[16], 16);
hexvalue (ctx->sregs->regs.psw.addr, regs[17], 16);
hexvalue (ctx->uc_mcontext.gregs[0], regs[0], 16);
hexvalue (ctx->uc_mcontext.gregs[1], regs[1], 16);
hexvalue (ctx->uc_mcontext.gregs[2], regs[2], 16);
hexvalue (ctx->uc_mcontext.gregs[3], regs[3], 16);
hexvalue (ctx->uc_mcontext.gregs[4], regs[4], 16);
hexvalue (ctx->uc_mcontext.gregs[5], regs[5], 16);
hexvalue (ctx->uc_mcontext.gregs[6], regs[6], 16);
hexvalue (ctx->uc_mcontext.gregs[7], regs[7], 16);
hexvalue (ctx->uc_mcontext.gregs[8], regs[8], 16);
hexvalue (ctx->uc_mcontext.gregs[9], regs[9], 16);
hexvalue (ctx->uc_mcontext.gregs[10], regs[10], 16);
hexvalue (ctx->uc_mcontext.gregs[11], regs[11], 16);
hexvalue (ctx->uc_mcontext.gregs[12], regs[12], 16);
hexvalue (ctx->uc_mcontext.gregs[13], regs[13], 16);
hexvalue (ctx->uc_mcontext.gregs[14], regs[14], 16);
hexvalue (ctx->uc_mcontext.gregs[15], regs[15], 16);
hexvalue (ctx->uc_mcontext.psw.mask, regs[16], 16);
hexvalue (ctx->uc_mcontext.psw.addr, regs[17], 16);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n GPR0: ");

View File

@ -16,7 +16,19 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <signal.h>
#define SIGCONTEXT struct sigcontext *
#define GET_PC(ctx) ((void *)((ctx)->sregs->regs.psw.addr))
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
#ifdef __s390x__
return ctx->uc_mcontext.psw.addr;
#else
return ctx->uc_mcontext.psw.addr & 0x7FFFFFFF;
#endif
}
#endif

View File

@ -1,32 +0,0 @@
/* Low-level statistical profiling support function. Linux/SH version.
Copyright (C) 1996-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
static void
__profil_counter (int signo, int _a2, int _a3, int _a4, struct sigcontext sc)
{
void *pc;
pc = (void *) sc.sc_pc;
profil_count (pc);
/* This is a hack to prevent the compiler from implementing the
above function call as a sibcall. The sibcall would overwrite
the signal context. */
asm volatile ("");
}

View File

@ -53,7 +53,7 @@ hexvalue (unsigned long int value, char *buf, size_t len)
}
static void
register_dump (int fd, struct sigcontext *ctx)
register_dump (int fd, struct ucontext_t *ctx)
{
char regs[22][8];
struct iovec iov[22 * 2 + 34 * 2 + 2];
@ -69,28 +69,28 @@ register_dump (int fd, struct sigcontext *ctx)
++nr
/* Generate strings of register contents. */
hexvalue (ctx->sc_regs[0], regs[0], 8);
hexvalue (ctx->sc_regs[1], regs[1], 8);
hexvalue (ctx->sc_regs[2], regs[2], 8);
hexvalue (ctx->sc_regs[3], regs[3], 8);
hexvalue (ctx->sc_regs[4], regs[4], 8);
hexvalue (ctx->sc_regs[5], regs[5], 8);
hexvalue (ctx->sc_regs[6], regs[6], 8);
hexvalue (ctx->sc_regs[7], regs[7], 8);
hexvalue (ctx->sc_regs[8], regs[8], 8);
hexvalue (ctx->sc_regs[9], regs[9], 8);
hexvalue (ctx->sc_regs[10], regs[10], 8);
hexvalue (ctx->sc_regs[11], regs[11], 8);
hexvalue (ctx->sc_regs[12], regs[12], 8);
hexvalue (ctx->sc_regs[13], regs[13], 8);
hexvalue (ctx->sc_regs[14], regs[14], 8);
hexvalue (ctx->sc_regs[15], regs[15], 8);
hexvalue (ctx->sc_macl, regs[16], 8);
hexvalue (ctx->sc_mach, regs[17], 8);
hexvalue (ctx->sc_pc, regs[18], 8);
hexvalue (ctx->sc_pr, regs[19], 8);
hexvalue (ctx->sc_gbr, regs[20], 8);
hexvalue (ctx->sc_sr, regs[21], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R0], regs[0], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R1], regs[1], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R2], regs[2], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R3], regs[3], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R4], regs[4], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R5], regs[5], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R6], regs[6], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R7], regs[7], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R8], regs[8], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R9], regs[9], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R10], regs[10], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R11], regs[11], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R12], regs[12], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R13], regs[13], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R14], regs[14], 8);
hexvalue (ctx->uc_mcontext.gregs[REG_R15], regs[15], 8);
hexvalue (ctx->uc_mcontext.macl, regs[16], 8);
hexvalue (ctx->uc_mcontext.mach, regs[17], 8);
hexvalue (ctx->uc_mcontext.pc, regs[18], 8);
hexvalue (ctx->uc_mcontext.pr, regs[19], 8);
hexvalue (ctx->uc_mcontext.gbr, regs[20], 8);
hexvalue (ctx->uc_mcontext.sr, regs[21], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n R0: ");
@ -144,42 +144,42 @@ register_dump (int fd, struct sigcontext *ctx)
#ifdef __SH_FPU_ANY__
char fpregs[34][8];
if (ctx->sc_ownedfp != 0)
if (ctx->uc_mcontext.ownedfp != 0)
{
hexvalue (ctx->sc_fpregs[0], fpregs[0], 8);
hexvalue (ctx->sc_fpregs[1], fpregs[1], 8);
hexvalue (ctx->sc_fpregs[2], fpregs[2], 8);
hexvalue (ctx->sc_fpregs[3], fpregs[3], 8);
hexvalue (ctx->sc_fpregs[4], fpregs[4], 8);
hexvalue (ctx->sc_fpregs[5], fpregs[5], 8);
hexvalue (ctx->sc_fpregs[6], fpregs[6], 8);
hexvalue (ctx->sc_fpregs[7], fpregs[7], 8);
hexvalue (ctx->sc_fpregs[8], fpregs[8], 8);
hexvalue (ctx->sc_fpregs[9], fpregs[9], 8);
hexvalue (ctx->sc_fpregs[10], fpregs[10], 8);
hexvalue (ctx->sc_fpregs[11], fpregs[11], 8);
hexvalue (ctx->sc_fpregs[12], fpregs[12], 8);
hexvalue (ctx->sc_fpregs[13], fpregs[13], 8);
hexvalue (ctx->sc_fpregs[14], fpregs[14], 8);
hexvalue (ctx->sc_fpregs[15], fpregs[15], 8);
hexvalue (ctx->sc_xfpregs[0], fpregs[16], 8);
hexvalue (ctx->sc_xfpregs[1], fpregs[17], 8);
hexvalue (ctx->sc_xfpregs[2], fpregs[18], 8);
hexvalue (ctx->sc_xfpregs[3], fpregs[19], 8);
hexvalue (ctx->sc_xfpregs[4], fpregs[20], 8);
hexvalue (ctx->sc_xfpregs[5], fpregs[21], 8);
hexvalue (ctx->sc_xfpregs[6], fpregs[22], 8);
hexvalue (ctx->sc_xfpregs[7], fpregs[23], 8);
hexvalue (ctx->sc_xfpregs[8], fpregs[24], 8);
hexvalue (ctx->sc_xfpregs[9], fpregs[25], 8);
hexvalue (ctx->sc_xfpregs[10], fpregs[26], 8);
hexvalue (ctx->sc_xfpregs[11], fpregs[27], 8);
hexvalue (ctx->sc_xfpregs[12], fpregs[28], 8);
hexvalue (ctx->sc_xfpregs[13], fpregs[29], 8);
hexvalue (ctx->sc_xfpregs[14], fpregs[30], 8);
hexvalue (ctx->sc_xfpregs[15], fpregs[31], 8);
hexvalue (ctx->sc_fpscr, fpregs[32], 8);
hexvalue (ctx->sc_fpul, fpregs[33], 8);
hexvalue (ctx->uc_mcontext.fpregs[0], fpregs[0], 8);
hexvalue (ctx->uc_mcontext.fpregs[1], fpregs[1], 8);
hexvalue (ctx->uc_mcontext.fpregs[2], fpregs[2], 8);
hexvalue (ctx->uc_mcontext.fpregs[3], fpregs[3], 8);
hexvalue (ctx->uc_mcontext.fpregs[4], fpregs[4], 8);
hexvalue (ctx->uc_mcontext.fpregs[5], fpregs[5], 8);
hexvalue (ctx->uc_mcontext.fpregs[6], fpregs[6], 8);
hexvalue (ctx->uc_mcontext.fpregs[7], fpregs[7], 8);
hexvalue (ctx->uc_mcontext.fpregs[8], fpregs[8], 8);
hexvalue (ctx->uc_mcontext.fpregs[9], fpregs[9], 8);
hexvalue (ctx->uc_mcontext.fpregs[10], fpregs[10], 8);
hexvalue (ctx->uc_mcontext.fpregs[11], fpregs[11], 8);
hexvalue (ctx->uc_mcontext.fpregs[12], fpregs[12], 8);
hexvalue (ctx->uc_mcontext.fpregs[13], fpregs[13], 8);
hexvalue (ctx->uc_mcontext.fpregs[14], fpregs[14], 8);
hexvalue (ctx->uc_mcontext.fpregs[15], fpregs[15], 8);
hexvalue (ctx->uc_mcontext.xfpregs[0], fpregs[16], 8);
hexvalue (ctx->uc_mcontext.xfpregs[1], fpregs[17], 8);
hexvalue (ctx->uc_mcontext.xfpregs[2], fpregs[18], 8);
hexvalue (ctx->uc_mcontext.xfpregs[3], fpregs[19], 8);
hexvalue (ctx->uc_mcontext.xfpregs[4], fpregs[20], 8);
hexvalue (ctx->uc_mcontext.xfpregs[5], fpregs[21], 8);
hexvalue (ctx->uc_mcontext.xfpregs[6], fpregs[22], 8);
hexvalue (ctx->uc_mcontext.xfpregs[7], fpregs[23], 8);
hexvalue (ctx->uc_mcontext.xfpregs[8], fpregs[24], 8);
hexvalue (ctx->uc_mcontext.xfpregs[9], fpregs[25], 8);
hexvalue (ctx->uc_mcontext.xfpregs[10], fpregs[26], 8);
hexvalue (ctx->uc_mcontext.xfpregs[11], fpregs[27], 8);
hexvalue (ctx->uc_mcontext.xfpregs[12], fpregs[28], 8);
hexvalue (ctx->uc_mcontext.xfpregs[13], fpregs[29], 8);
hexvalue (ctx->uc_mcontext.xfpregs[14], fpregs[30], 8);
hexvalue (ctx->uc_mcontext.xfpregs[15], fpregs[31], 8);
hexvalue (ctx->uc_mcontext.fpscr, fpregs[32], 8);
hexvalue (ctx->uc_mcontext.fpul, fpregs[33], 8);
ADD_STRING ("\n\n FR0: ");
ADD_MEM (fpregs[0], 8);
@ -260,4 +260,4 @@ register_dump (int fd, struct sigcontext *ctx)
}
#define REGISTER_DUMP register_dump (fd, &ctx)
#define REGISTER_DUMP register_dump (fd, ctx)

View File

@ -1,150 +0,0 @@
/* Dump registers.
Copyright (C) 1999-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <sys/uio.h>
#include <_itoa.h>
/* We will print the register dump in this format:
R0: XXXXXXXX R1: XXXXXXXX R2: XXXXXXXX R3: XXXXXXXX
R4: XXXXXXXX R5: XXXXXXXX R6: XXXXXXXX R7: XXXXXXXX
R8: XXXXXXXX R9: XXXXXXXX R10: XXXXXXXX R11: XXXXXXXX
R12: XXXXXXXX R13: XXXXXXXX R14: XXXXXXXX R15: XXXXXXXX
MACL: XXXXXXXX MACH: XXXXXXXX
PC: XXXXXXXX PR: XXXXXXXX GBR: XXXXXXXX SR: XXXXXXXX
FR0: XXXXXXXX FR1: XXXXXXXX FR2: XXXXXXXX FR3: XXXXXXXX
FR4: XXXXXXXX FR5: XXXXXXXX FR6: XXXXXXXX FR7: XXXXXXXX
FR8: XXXXXXXX FR9: XXXXXXXX FR10: XXXXXXXX FR11: XXXXXXXX
FR12: XXXXXXXX FR13: XXXXXXXX FR14: XXXXXXXX FR15: XXXXXXXX
XR0: XXXXXXXX XR1: XXXXXXXX XR2: XXXXXXXX XR3: XXXXXXXX
XR4: XXXXXXXX XR5: XXXXXXXX XR6: XXXXXXXX XR7: XXXXXXXX
XR8: XXXXXXXX XR9: XXXXXXXX XR10: XXXXXXXX XR11: XXXXXXXX
XR12: XXXXXXXX XR13: XXXXXXXX XR14: XXXXXXXX XR15: XXXXXXXX
FPSCR: XXXXXXXX FPUL: XXXXXXXX
*/
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[22][8];
struct iovec iov[112];
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->sc_regs[0], regs[0], 8);
hexvalue (ctx->sc_regs[1], regs[1], 8);
hexvalue (ctx->sc_regs[2], regs[2], 8);
hexvalue (ctx->sc_regs[3], regs[3], 8);
hexvalue (ctx->sc_regs[4], regs[4], 8);
hexvalue (ctx->sc_regs[5], regs[5], 8);
hexvalue (ctx->sc_regs[6], regs[6], 8);
hexvalue (ctx->sc_regs[7], regs[7], 8);
hexvalue (ctx->sc_regs[8], regs[8], 8);
hexvalue (ctx->sc_regs[9], regs[9], 8);
hexvalue (ctx->sc_regs[10], regs[10], 8);
hexvalue (ctx->sc_regs[11], regs[11], 8);
hexvalue (ctx->sc_regs[12], regs[12], 8);
hexvalue (ctx->sc_regs[13], regs[13], 8);
hexvalue (ctx->sc_regs[14], regs[14], 8);
hexvalue (ctx->sc_regs[15], regs[15], 8);
hexvalue (ctx->sc_macl, regs[16], 8);
hexvalue (ctx->sc_mach, regs[17], 8);
hexvalue (ctx->sc_pc, regs[18], 8);
hexvalue (ctx->sc_pr, regs[19], 8);
hexvalue (ctx->sc_gbr, regs[20], 8);
hexvalue (ctx->sc_sr, regs[21], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n R0: ");
ADD_MEM (regs[0], 8);
ADD_STRING (" R1: ");
ADD_MEM (regs[1], 8);
ADD_STRING (" R2: ");
ADD_MEM (regs[2], 8);
ADD_STRING (" R3: ");
ADD_MEM (regs[3], 8);
ADD_STRING ("\n R4: ");
ADD_MEM (regs[4], 8);
ADD_STRING (" R5: ");
ADD_MEM (regs[5], 8);
ADD_STRING (" R6: ");
ADD_MEM (regs[6], 8);
ADD_STRING (" R7: ");
ADD_MEM (regs[7], 8);
ADD_STRING ("\n R8: ");
ADD_MEM (regs[8], 8);
ADD_STRING (" R9: ");
ADD_MEM (regs[9], 8);
ADD_STRING (" R10: ");
ADD_MEM (regs[10], 8);
ADD_STRING (" R11: ");
ADD_MEM (regs[11], 8);
ADD_STRING ("\n R12: ");
ADD_MEM (regs[12], 8);
ADD_STRING (" R13: ");
ADD_MEM (regs[13], 8);
ADD_STRING (" R14: ");
ADD_MEM (regs[14], 8);
ADD_STRING (" R15: ");
ADD_MEM (regs[15], 8);
ADD_STRING ("\n\nMACL: ");
ADD_MEM (regs[16], 8);
ADD_STRING (" MACH: ");
ADD_MEM (regs[17], 8);
ADD_STRING ("\n\n PC: ");
ADD_MEM (regs[18], 8);
ADD_STRING (" PR: ");
ADD_MEM (regs[19], 8);
ADD_STRING (" GBR: ");
ADD_MEM (regs[20], 8);
ADD_STRING (" SR: ");
ADD_MEM (regs[21], 8);
ADD_STRING ("\n");
/* Write the stuff out. */
writev (fd, iov, nr);
}
#define REGISTER_DUMP register_dump (fd, &ctx)

View File

@ -16,6 +16,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT int _a2, int _a3, int _a4, struct sigcontext
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#define GET_PC(ctx) ((void *) ctx.sc_pc)
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.pc;
}
#endif

View File

@ -18,11 +18,17 @@
#include <signal.h>
void
__profil_counter (int signo, struct sigcontext *si)
{
profil_count ((void *) si->sigc_regs.tpc);
}
#include <sysdeps/unix/sysv/linux/profil-counter.h>
#ifndef __profil_counter
weak_alias (__profil_counter, profil_counter)
void
__profil_counter_global (int signo, struct sigcontext *si)
{
#ifdef __arch64__
profil_count (si->sigc_regs.tpc);
#else
profil_count (si->si_regs.pc);
#endif
}
weak_alias (__profil_counter_global, profil_counter)
#endif

View File

@ -1,28 +0,0 @@
/* Low-level statistical profiling support function. Linux/SPARC version.
Copyright (C) 1997-2019 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 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, see
<http://www.gnu.org/licenses/>. */
#include <signal.h>
void
__profil_counter (int signo, struct sigcontext *si)
{
profil_count ((void *) si->si_regs.pc);
}
#ifndef __profil_counter
weak_alias (__profil_counter, profil_counter)
#endif

View File

@ -84,16 +84,23 @@ struct __siginfo_sparc64_fpu
unsigned int si_fprs;
};
/* Unlike other architectures, sparc32 passes pt_regs32 REGS pointer as
the third argument to a sa_sigaction handler with SA_SIGINFO enabled. */
static void
register_dump (int fd, SIGCONTEXT ctx)
register_dump (int fd, void *ctx)
{
char regs[36][8];
char fregs[68][8];
struct iovec iov[150];
size_t nr = 0;
int i;
unsigned int *r = (unsigned int *)
ctx->si_regs.u_regs[14];
struct pt_regs32 *ptregs = (struct pt_regs32 *) ctx;
struct compat_sigset_t
{
unsigned int sig[2];
};
struct compat_sigset_t *mask = (struct compat_sigset_t *)(ptregs + 1);
unsigned int *r = (unsigned int *) ptregs->u_regs[14];
#define ADD_STRING(str) \
iov[nr].iov_base = (char *) str; \
@ -105,15 +112,16 @@ register_dump (int fd, SIGCONTEXT ctx)
++nr
/* Generate strings of register contents. */
hexvalue (ctx->si_regs.psr, regs[0], 8);
hexvalue (ctx->si_regs.pc, regs[1], 8);
hexvalue (ctx->si_regs.npc, regs[2], 8);
hexvalue (ctx->si_regs.y, regs[3], 8);
hexvalue (ptregs->psr, regs[0], 8);
hexvalue (ptregs->pc, regs[1], 8);
hexvalue (ptregs->npc, regs[2], 8);
hexvalue (ptregs->y, regs[3], 8);
for (i = 1; i <= 15; i++)
hexvalue (ctx->si_regs.u_regs[i], regs[3+i], 8);
hexvalue (ptregs->u_regs[i], regs[3+i], 8);
for (i = 0; i <= 15; i++)
hexvalue (r[i], regs[19+i], 8);
hexvalue (ctx->si_mask, regs[35], 8);
hexvalue (mask->sig[0], regs[35], 8);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n PSR: ");
@ -189,11 +197,11 @@ register_dump (int fd, SIGCONTEXT ctx)
ADD_STRING ("\n\n Old mask: ");
ADD_MEM (regs[35], 8);
if ((ctx->si_regs.psr & 0xff000000) == 0xff000000)
if ((ptregs->psr & 0xff000000) == 0xff000000)
{
struct __siginfo_sparc64_fpu *f;
struct __siginfo_sparc64_fpu *f = *(struct __siginfo_sparc64_fpu **)
(mask + 1);
f = *(struct __siginfo_sparc64_fpu **) (ctx + 1);
if (f != NULL)
{
for (i = 0; i < 64; i++)
@ -277,9 +285,9 @@ register_dump (int fd, SIGCONTEXT ctx)
}
else
{
struct __siginfo_sparc32_fpu *f;
struct __siginfo_sparc32_fpu *f = *(struct __siginfo_sparc32_fpu **)
(mask + 1);
f = *(struct __siginfo_sparc32_fpu **) (ctx + 1);
if (f != NULL)
{
for (i = 0; i < 32; i++)

View File

@ -16,5 +16,41 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define SIGCONTEXT struct sigcontext *
#define GET_PC(__ctx) ((void *) ((__ctx)->si_regs.pc))
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
/* The sparc32 kernel signal frame for SA_SIGINFO is defined as:
struct rt_signal_frame32
{
struct sparc_stackf32 ss;
compat_siginfo_t info;
struct pt_regs32 regs; <- void *ctx
compat_sigset_t mask;
u32 fpu_save;
unsigned int insns[2];
compat_stack_t stack;
unsigned int extra_size;
siginfo_extra_v8plus_t v8plus;
u32 rwin_save;
} __attribute__((aligned(8)));
Unlike other architectures, sparc32 passes pt_regs32 REGS pointer as
the third argument to a sa_sigaction handler with SA_SIGINFO enabled. */
struct pt_regs32
{
unsigned int psr;
unsigned int pc;
unsigned int npc;
unsigned int y;
unsigned int u_regs[16];
};
static inline uintptr_t
sigcontext_get_pc (const struct pt_regs32 *ctx)
{
return ctx->pc;
}
#endif

View File

@ -60,17 +60,36 @@ hexvalue (unsigned long int value, char *buf, size_t len)
*--cp = '0';
}
/* The sparc64 kernel signal frame for SA_SIGINFO is defined as:
struct rt_signal_frame
{
struct sparc_stackf ss;
siginfo_t info;
struct pt_regs regs; <- void *ctx
__siginfo_fpu_t *fpu_save;
stack_t stack;
sigset_t mask;
__siginfo_rwin_t *rwin_save;
};
Unlike other architectures, sparc32 passes pt_regs32 REGS pointers as
the third argument to a sa_sigaction handler with SA_SIGINFO enabled. */
static void
register_dump (int fd, SIGCONTEXT ctx)
register_dump (int fd, void *ctx)
{
char regs[36][16];
char fregs[68][8];
struct iovec iov[150];
size_t nr = 0;
int i;
unsigned long *r = (unsigned long *)
(ctx->sigc_regs.u_regs[14] + STACK_BIAS);
__siginfo_fpu_t *f;
struct pt_regs *ptregs = (struct pt_regs*) ((siginfo_t *)ctx + 1);
unsigned long *r = (unsigned long *) (ptregs->u_regs[14] + STACK_BIAS);
__siginfo_fpu_t *f = (__siginfo_fpu_t *)(ptregs + 1);
struct kernel_sigset_t {
unsigned long sig[1];
} *mask = (struct kernel_sigset_t *)((stack_t *)(f + 1) + 1);
#define ADD_STRING(str) \
iov[nr].iov_base = (char *) str; \
@ -82,15 +101,15 @@ register_dump (int fd, SIGCONTEXT ctx)
++nr
/* Generate strings of register contents. */
hexvalue (ctx->sigc_regs.tstate, regs[0], 16);
hexvalue (ctx->sigc_regs.tpc, regs[1], 16);
hexvalue (ctx->sigc_regs.tnpc, regs[2], 16);
hexvalue (ctx->sigc_regs.y, regs[3], 8);
hexvalue (ptregs->tstate, regs[0], 16);
hexvalue (ptregs->tpc, regs[1], 16);
hexvalue (ptregs->tnpc, regs[2], 16);
hexvalue (ptregs->y, regs[3], 8);
for (i = 1; i <= 15; i++)
hexvalue (ctx->sigc_regs.u_regs[i], regs[3+i], 16);
hexvalue (ptregs->u_regs[i], regs[3+i], 16);
for (i = 0; i <= 15; i++)
hexvalue (r[i], regs[19+i], 16);
hexvalue (ctx->sigc_mask, regs[35], 16);
hexvalue (r[i], regs[19+i], 16);
hexvalue (mask->sig[0], regs[35], 16);
/* Generate the output. */
ADD_STRING ("Register dump:\n\n TSTATE: ");
@ -166,7 +185,6 @@ register_dump (int fd, SIGCONTEXT ctx)
ADD_STRING ("\n\n Mask: ");
ADD_MEM (regs[35], 16);
f = ctx->sigc_fpu_save;
if (f != NULL)
{
for (i = 0; i < 64; i++)

View File

@ -16,8 +16,46 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#include <bits/types/siginfo_t.h>
/* The sparc64 kernel signal frame for SA_SIGINFO is defined as:
struct rt_signal_frame
{
struct sparc_stackf ss;
siginfo_t info;
struct pt_regs regs;
__siginfo_fpu_t *fpu_save;
stack_t stack;
sigset_t mask;
__siginfo_rwin_t *rwin_save;
};
Unlike other architectures, sparc64 passe the siginfo_t INFO pointer
as the third argument to a sa_sigaction handler with SA_SIGINFO enabled. */
#ifndef STACK_BIAS
#define STACK_BIAS 2047
#endif
#define SIGCONTEXT struct sigcontext *
#define GET_PC(__ctx) ((void *) ((__ctx)->sigc_regs.tpc))
struct pt_regs
{
unsigned long int u_regs[16];
unsigned long int tstate;
unsigned long int tpc;
unsigned long int tnpc;
unsigned int y;
unsigned int magic;
};
static inline uintptr_t
sigcontext_get_pc (const siginfo_t *ctx)
{
struct pt_regs *regs = (struct pt_regs*) ((siginfo_t *)(ctx) + 1);
return regs->tpc;
}
#endif

View File

@ -0,0 +1,78 @@
/* Test that the GET_PC macro is consistent with the unwinder.
Copyright (C) 2019 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 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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
/* This test searches for the value of the GET_PC macro in the
addresses obtained from the backtrace function. */
#include <array_length.h>
#include <execinfo.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <support/check.h>
#include <support/xsignal.h>
#include <sigcontextinfo.h>
static bool handler_called;
static void
handler (int signal, siginfo_t *info, void *ctx)
{
TEST_COMPARE (signal, SIGUSR1);
uintptr_t pc = sigcontext_get_pc (ctx);
printf ("info: address in signal handler: 0x%" PRIxPTR "\n", pc);
void *callstack[10];
int callstack_count = backtrace (callstack, array_length (callstack));
TEST_VERIFY_EXIT (callstack_count > 0);
TEST_VERIFY_EXIT (callstack_count <= array_length (callstack));
bool found = false;
for (int i = 0; i < callstack_count; ++i)
{
const char *marker;
if ((uintptr_t) callstack[i] == pc)
{
found = true;
marker = " *";
}
else
marker = "";
printf ("info: call stack entry %d: 0x%" PRIxPTR "%s\n",
i, (uintptr_t) callstack[i], marker);
}
TEST_VERIFY (found);
handler_called = true;
}
static int
do_test (void)
{
struct sigaction sa =
{
.sa_sigaction = &handler,
.sa_flags = SA_SIGINFO
};
xsigaction (SIGUSR1, &sa, NULL);
raise (SIGUSR1);
TEST_VERIFY (handler_called);
return 0;
}
#include <support/test-driver.c>

View File

@ -15,8 +15,13 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdint.h>
#ifndef _SIGCONTEXTINFO_H
#define _SIGCONTEXTINFO_H
#define SIGCONTEXT siginfo_t *_si, ucontext_t *
#define GET_PC(ctx) \
((void *) (uintptr_t) (ctx)->uc_mcontext.gregs[REG_RIP])
static inline uintptr_t
sigcontext_get_pc (const ucontext_t *ctx)
{
return ctx->uc_mcontext.gregs[REG_RIP];
}
#endif