1 /* Dump registers.
2    Copyright (C) 1998-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <stddef.h>
20 #include <sys/uio.h>
21 #include <_itoa.h>
22 
23 /* We will print the register dump in this format:
24 
25   D0: XXXXXXXX   D1: XXXXXXXX   D2: XXXXXXXX   D3: XXXXXXXX
26   D4: XXXXXXXX   D5: XXXXXXXX   D6: XXXXXXXX   D7: XXXXXXXX
27   A0: XXXXXXXX   A1: XXXXXXXX   A2: XXXXXXXX   A3: XXXXXXXX
28   A4: XXXXXXXX   A5: XXXXXXXX   A6: XXXXXXXX   A7: XXXXXXXX
29   PC: XXXXXXXX   SR: XXXX
30 
31   OldMask: XXXXXXXX  Vector: XXXX
32 
33   FP0: XXXXXXXXXXXXXXXXXXXXXXXX   FP1: XXXXXXXXXXXXXXXXXXXXXXXX
34   FP2: XXXXXXXXXXXXXXXXXXXXXXXX   FP3: XXXXXXXXXXXXXXXXXXXXXXXX
35   FP4: XXXXXXXXXXXXXXXXXXXXXXXX   FP5: XXXXXXXXXXXXXXXXXXXXXXXX
36   FP6: XXXXXXXXXXXXXXXXXXXXXXXX   FP7: XXXXXXXXXXXXXXXXXXXXXXXX
37   FPCR: XXXXXXXX   FPSR: XXXXXXXX   FPIAR: XXXXXXXX
38 
39 */
40 
41 #define FPCONTEXT_SIZE  216
42 #define uc_formatvec    __glibc_reserved1[FPCONTEXT_SIZE/4]
43 #define uc_oldmask      uc_sigmask.__val[0]
44 
45 static void
hexvalue(unsigned long int value,char * buf,size_t len)46 hexvalue (unsigned long int value, char *buf, size_t len)
47 {
48   char *cp = _itoa_word (value, buf + len, 16, 0);
49   while (cp > buf)
50     *--cp = '0';
51 }
52 
53 static void
register_dump(int fd,struct ucontext_t * ctx)54 register_dump (int fd, struct ucontext_t *ctx)
55 {
56   char regs[20][8];
57   char fpregs[11][24];
58   struct iovec iov[63], *next_iov = iov;
59   int i, j, fpreg_size;
60 
61 #define ADD_STRING(str) \
62   next_iov->iov_base = (char *) (str); \
63   next_iov->iov_len = strlen (str); \
64   ++next_iov
65 #define ADD_MEM(str, len) \
66   next_iov->iov_base = (str); \
67   next_iov->iov_len = (len); \
68   ++next_iov
69 
70 #ifdef __mcoldfire__
71   fpreg_size = 16;
72 #else
73   fpreg_size = 24;
74 #endif
75 
76   /* Generate strings of register contents.  */
77   hexvalue (ctx->uc_mcontext.gregs[R_D0], regs[0], 8);
78   hexvalue (ctx->uc_mcontext.gregs[R_D1], regs[1], 8);
79   hexvalue (ctx->uc_mcontext.gregs[R_D2], regs[2], 8);
80   hexvalue (ctx->uc_mcontext.gregs[R_D3], regs[3], 8);
81   hexvalue (ctx->uc_mcontext.gregs[R_D4], regs[4], 8);
82   hexvalue (ctx->uc_mcontext.gregs[R_D5], regs[5], 8);
83   hexvalue (ctx->uc_mcontext.gregs[R_D6], regs[6], 8);
84   hexvalue (ctx->uc_mcontext.gregs[R_D7], regs[7], 8);
85   hexvalue (ctx->uc_mcontext.gregs[R_A0], regs[8], 8);
86   hexvalue (ctx->uc_mcontext.gregs[R_A1], regs[9], 8);
87   hexvalue (ctx->uc_mcontext.gregs[R_A2], regs[10], 8);
88   hexvalue (ctx->uc_mcontext.gregs[R_A3], regs[11], 8);
89   hexvalue (ctx->uc_mcontext.gregs[R_A4], regs[12], 8);
90   hexvalue (ctx->uc_mcontext.gregs[R_A5], regs[13], 8);
91   hexvalue (ctx->uc_mcontext.gregs[R_A6], regs[14], 8);
92   hexvalue (ctx->uc_mcontext.gregs[R_SP], regs[15], 8);
93   hexvalue (ctx->uc_mcontext.gregs[R_PC], regs[16], 8);
94   hexvalue (ctx->uc_mcontext.gregs[R_PS], regs[17], 4);
95   hexvalue (ctx->uc_oldmask, regs[18], 8);
96   hexvalue (ctx->uc_formatvec & 0xfff, regs[19], 4);
97 
98   for (i = 0; i < 8; i++)
99     for (j = 0; j < fpreg_size; j += 8)
100       hexvalue (ctx->uc_mcontext.fpregs.f_fpregs[i][j/8], fpregs[i] + j, 8);
101   hexvalue (ctx->uc_mcontext.fpregs.f_pcr, fpregs[8], 8);
102   hexvalue (ctx->uc_mcontext.fpregs.f_psr, fpregs[9], 8);
103   hexvalue (ctx->uc_mcontext.fpregs.f_fpiaddr, fpregs[10], 8);
104 
105   /* Generate the output.  */
106   ADD_STRING ("Register dump:\n\n  D0: ");
107   ADD_MEM (regs[0], 8);
108   ADD_STRING ("  D1: ");
109   ADD_MEM (regs[1], 8);
110   ADD_STRING ("  D2: ");
111   ADD_MEM (regs[2], 8);
112   ADD_STRING ("  D3: ");
113   ADD_MEM (regs[3], 8);
114   ADD_STRING ("\n  D4: ");
115   ADD_MEM (regs[4], 8);
116   ADD_STRING ("  D5: ");
117   ADD_MEM (regs[5], 8);
118   ADD_STRING ("  D6: ");
119   ADD_MEM (regs[6], 8);
120   ADD_STRING ("  D7: ");
121   ADD_MEM (regs[7], 8);
122   ADD_STRING ("\n  A0: ");
123   ADD_MEM (regs[8], 8);
124   ADD_STRING ("  A1: ");
125   ADD_MEM (regs[9], 8);
126   ADD_STRING ("  A2: ");
127   ADD_MEM (regs[10], 8);
128   ADD_STRING ("  A3: ");
129   ADD_MEM (regs[11], 8);
130   ADD_STRING ("\n  A4: ");
131   ADD_MEM (regs[12], 8);
132   ADD_STRING ("  A5: ");
133   ADD_MEM (regs[13], 8);
134   ADD_STRING ("  A6: ");
135   ADD_MEM (regs[14], 8);
136   ADD_STRING ("  A7: ");
137   ADD_MEM (regs[15], 8);
138   ADD_STRING ("\n  PC: ");
139   ADD_MEM (regs[16], 8);
140   ADD_STRING ("  SR: ");
141   ADD_MEM (regs[17], 4);
142 
143   ADD_STRING ("\n\n  OldMask: ");
144   ADD_MEM (regs[18], 8);
145   ADD_STRING ("  Vector: ");
146   ADD_MEM (regs[19], 4);
147 
148   ADD_STRING ("\n\n  FP0: ");
149   ADD_MEM (fpregs[0], fpreg_size);
150   ADD_STRING ("  FP1: ");
151   ADD_MEM (fpregs[1], fpreg_size);
152   ADD_STRING ("\n  FP2: ");
153   ADD_MEM (fpregs[2], fpreg_size);
154   ADD_STRING ("  FP3: ");
155   ADD_MEM (fpregs[3], fpreg_size);
156   ADD_STRING ("\n  FP4: ");
157   ADD_MEM (fpregs[4], fpreg_size);
158   ADD_STRING ("  FP5: ");
159   ADD_MEM (fpregs[5], fpreg_size);
160   ADD_STRING ("\n  FP6: ");
161   ADD_MEM (fpregs[6], fpreg_size);
162   ADD_STRING ("  FP7: ");
163   ADD_MEM (fpregs[7], fpreg_size);
164   ADD_STRING ("\n  FPCR: ");
165   ADD_MEM (fpregs[8], 8);
166   ADD_STRING ("  FPSR: ");
167   ADD_MEM (fpregs[9], 8);
168   ADD_STRING ("  FPIAR: ");
169   ADD_MEM (fpregs[10], 8);
170   ADD_STRING ("\n");
171 
172   /* Write the stuff out.  */
173   writev (fd, iov, next_iov - iov);
174 }
175 
176 #define REGISTER_DUMP register_dump (fd, ctx)
177