about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/alpha
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2018-12-17 16:44:14 -0200
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2019-08-23 11:30:56 -0300
commita43565ac447b1608ae2626f5012673560bb623ab (patch)
treec759caab740e9ab6ed830edcef55b33f06ec665c /sysdeps/unix/sysv/linux/alpha
parent624c109b2a273dbfd6f87795a64ac1f6c5d89f10 (diff)
downloadglibc-a43565ac447b1608ae2626f5012673560bb623ab.tar.gz
glibc-a43565ac447b1608ae2626f5012673560bb623ab.tar.xz
glibc-a43565ac447b1608ae2626f5012673560bb623ab.zip
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.
Diffstat (limited to 'sysdeps/unix/sysv/linux/alpha')
-rw-r--r--sysdeps/unix/sysv/linux/alpha/register-dump.h283
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h15
2 files changed, 196 insertions, 102 deletions
diff --git a/sysdeps/unix/sysv/linux/alpha/register-dump.h b/sysdeps/unix/sysv/linux/alpha/register-dump.h
index 9d55bc0fc5..45dafe0a1f 100644
--- a/sysdeps/unix/sysv/linux/alpha/register-dump.h
+++ b/sysdeps/unix/sysv/linux/alpha/register-dump.h
@@ -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] =
-{
-  "    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] =
+static void
+hexvalue (unsigned long int value, char *buf, size_t len)
 {
-  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;
-
-  p = stpcpy (p, "Register dump:\n\n");
-
-  for (i = 0; i < NREGS; ++i)
-    {
-      int this_offset, this_lf;
-      unsigned long val;
-      signed long j;
-
-      this_offset = offsets[i];
-      this_lf = this_offset & 7;
-
-      val = *(unsigned long *)(((size_t)ctx + this_offset) & -8);
-
-      memcpy (p, regnames[i], 8);
-      p += 8;
-
-      for (j = 60; j >= 0; j -= 4)
-	{
-	  unsigned long x = (val >> j) & 15;
-	  x += x < 10 ? '0' : 'a' - 10;
-	  *p++ = x;
-	}
-
-      if (this_lf > 0)
-	{
-	  if (this_lf > 1)
-	    *p++ = '\n';
-	  *p++ = '\n';
-	}
-    }
-
-  write (fd, buf, p - buf);
+  struct iovec iov[31 * 2 + 2    /* REGS + PC.  */
+                   + 31 * 2 + 2  /* FREGS + FPCR.  */
+                   + (3 * 2)     /* TA0, TA1, TA3.  */
+                   + 1           /* '\n'.  */];
+  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
+
+  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);
+
+  /* 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);
+
+  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);
+
+  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);
+
+  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);
+
+  ADD_STRING ("\n");
+
+  /* Write the stuff out.  */
+  writev (fd, iov, nr);
 }
 
 #define REGISTER_DUMP register_dump (fd, ctx)
diff --git a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
index 45d06f9a12..6147ba5f52 100644
--- a/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
+++ b/sysdeps/unix/sysv/linux/alpha/sigcontextinfo.h
@@ -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