|
0 |
From 56915d38b2422deff54c90bd53ea03c834b3b513 Mon Sep 17 00:00:00 2001
|
|
1 |
From: Takashi YOSHII <yoshii.takashi@renesas.com>
|
|
2 |
Date: Mon, 8 Mar 2010 10:45:54 +0900
|
|
3 |
Subject: [PATCH] Add Renesas SuperH native support
|
|
4 |
|
|
5 |
---
|
|
6 |
gdb/Makefile.in | 1 +
|
|
7 |
gdb/config/sh/linux.mh | 8 +
|
|
8 |
gdb/config/sh/nm-linux.h | 54 ++++
|
|
9 |
gdb/config/sh/xm-linux.h | 32 ++
|
|
10 |
gdb/configure.host | 1 +
|
|
11 |
gdb/sh-linux-nat.c | 269 ++++++++++++++++++
|
|
12 |
gdb/sh-linux-tdep.c | 519 ++++++++++++++++++++++++++++++++++
|
|
13 |
gdb/sh-tdep.c | 54 ++--
|
|
14 |
gdb/sh-tdep.h | 49 ++++
|
|
15 |
gdb/testsuite/gdb.asm/asm-source.exp | 5 +
|
|
16 |
gdb/testsuite/gdb.asm/sh-linux.inc | 78 +++++
|
|
17 |
gdb/testsuite/gdb.asm/sh.inc | 3 +-
|
|
18 |
gdb/testsuite/gdb.base/annota1.c | 6 +-
|
|
19 |
gdb/testsuite/gdb.base/annota3.c | 6 +-
|
|
20 |
gdb/testsuite/gdb.base/sigall.c | 6 +-
|
|
21 |
gdb/testsuite/gdb.base/signals.c | 8 +-
|
|
22 |
16 files changed, 1057 insertions(+), 42 deletions(-)
|
|
23 |
create mode 100644 gdb/config/sh/linux.mh
|
|
24 |
create mode 100644 gdb/config/sh/nm-linux.h
|
|
25 |
create mode 100644 gdb/config/sh/xm-linux.h
|
|
26 |
create mode 100644 gdb/sh-linux-nat.c
|
|
27 |
create mode 100644 gdb/testsuite/gdb.asm/sh-linux.inc
|
|
28 |
|
|
29 |
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
|
|
30 |
index 72b546d..4325d5f 100644
|
|
31 |
--- a/gdb/Makefile.in
|
|
32 |
+++ b/gdb/Makefile.in
|
|
33 |
@@ -1476,6 +1476,7 @@ ALLDEPFILES = \
|
|
34 |
score-tdep.c \
|
|
35 |
ser-go32.c ser-pipe.c ser-tcp.c ser-mingw.c \
|
|
36 |
sh-tdep.c sh64-tdep.c shnbsd-tdep.c shnbsd-nat.c \
|
|
37 |
+ sh-linux-tdep.c sh-linux-nat.c \
|
|
38 |
sol2-tdep.c \
|
|
39 |
solib-irix.c solib-svr4.c solib-sunos.c \
|
|
40 |
sparc-linux-nat.c sparc-linux-tdep.c \
|
|
41 |
diff --git a/gdb/config/sh/linux.mh b/gdb/config/sh/linux.mh
|
|
42 |
new file mode 100644
|
|
43 |
index 0000000..86fa8b9
|
|
44 |
--- /dev/null
|
|
45 |
+++ b/gdb/config/sh/linux.mh
|
|
46 |
@@ -0,0 +1,8 @@
|
|
47 |
+# Host: Renesas Super-H running GNU/Linux
|
|
48 |
+NAT_FILE= nm-linux.h
|
|
49 |
+NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \
|
|
50 |
+ sh-linux-nat.o \
|
|
51 |
+ proc-service.o linux-thread-db.o gcore.o \
|
|
52 |
+ linux-nat.o linux-fork.o
|
|
53 |
+
|
|
54 |
+LOADLIBES= -ldl -rdynamic
|
|
55 |
diff --git a/gdb/config/sh/nm-linux.h b/gdb/config/sh/nm-linux.h
|
|
56 |
new file mode 100644
|
|
57 |
index 0000000..4e6fd5a
|
|
58 |
--- /dev/null
|
|
59 |
+++ b/gdb/config/sh/nm-linux.h
|
|
60 |
@@ -0,0 +1,54 @@
|
|
61 |
+/* Native-dependent definitions for SuperH running Linux, for GDB.
|
|
62 |
+ Copyright 2004 Free Software Foundation, Inc.
|
|
63 |
+
|
|
64 |
+ This file is part of GDB.
|
|
65 |
+
|
|
66 |
+ This program is free software; you can redistribute it and/or modify
|
|
67 |
+ it under the terms of the GNU General Public License as published by
|
|
68 |
+ the Free Software Foundation; either version 2 of the License, or
|
|
69 |
+ (at your option) any later version.
|
|
70 |
+
|
|
71 |
+ This program is distributed in the hope that it will be useful,
|
|
72 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
73 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
74 |
+ GNU General Public License for more details.
|
|
75 |
+
|
|
76 |
+ You should have received a copy of the GNU General Public License
|
|
77 |
+ along with this program; if not, write to the Free Software
|
|
78 |
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|
79 |
+ Boston, MA 02111-1307, USA. */
|
|
80 |
+
|
|
81 |
+#ifndef NM_LINUX_H
|
|
82 |
+#define NM_LINUX_H
|
|
83 |
+
|
|
84 |
+/* Get generic Linux native definitions. */
|
|
85 |
+#include "config/nm-linux.h"
|
|
86 |
+/* Support for the user area. */
|
|
87 |
+
|
|
88 |
+/* Return the size of the user struct. */
|
|
89 |
+extern int kernel_u_size (void);
|
|
90 |
+#define KERNEL_U_SIZE kernel_u_size()
|
|
91 |
+
|
|
92 |
+/* This is the amount to substract from u.u_ar0 to get the offset in
|
|
93 |
+ the core file of the register values. */
|
|
94 |
+#define KERNEL_U_ADDR 0
|
|
95 |
+
|
|
96 |
+#define U_REGS_OFFSET 0
|
|
97 |
+
|
|
98 |
+extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regnum);
|
|
99 |
+#define REGISTER_U_ADDR(addr, blockend, regnum) \
|
|
100 |
+ (addr) = register_u_addr (blockend, regnum)
|
|
101 |
+
|
|
102 |
+/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
|
|
103 |
+#define FETCH_INFERIOR_REGISTERS
|
|
104 |
+
|
|
105 |
+/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we
|
|
106 |
+ might fall back on the code `infptrace.c' (well a copy of that code
|
|
107 |
+ in `sh-linux-nat.c' for now) and we can access only the
|
|
108 |
+ general-purpose registers in that way. */
|
|
109 |
+extern int cannot_fetch_register (int regno);
|
|
110 |
+extern int cannot_store_register (int regno);
|
|
111 |
+#define CANNOT_FETCH_REGISTER(regno) cannot_fetch_register (regno)
|
|
112 |
+#define CANNOT_STORE_REGISTER(regno) cannot_store_register (regno)
|
|
113 |
+
|
|
114 |
+#endif /* NM_LINUX_H */
|
|
115 |
diff --git a/gdb/config/sh/xm-linux.h b/gdb/config/sh/xm-linux.h
|
|
116 |
new file mode 100644
|
|
117 |
index 0000000..6482093
|
|
118 |
--- /dev/null
|
|
119 |
+++ b/gdb/config/sh/xm-linux.h
|
|
120 |
@@ -0,0 +1,32 @@
|
|
121 |
+/* Native support for GNU/Linux, for GDB, the GNU debugger.
|
|
122 |
+ Copyright (C) 2000 Free Software Foundation, Inc.
|
|
123 |
+
|
|
124 |
+This file is part of GDB.
|
|
125 |
+
|
|
126 |
+This program is free software; you can redistribute it and/or modify
|
|
127 |
+it under the terms of the GNU General Public License as published by
|
|
128 |
+the Free Software Foundation; either version 2 of the License, or
|
|
129 |
+(at your option) any later version.
|
|
130 |
+
|
|
131 |
+This program is distributed in the hope that it will be useful,
|
|
132 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
133 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
134 |
+GNU General Public License for more details.
|
|
135 |
+
|
|
136 |
+You should have received a copy of the GNU General Public License
|
|
137 |
+along with this program; if not, write to the Free Software
|
|
138 |
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
139 |
+
|
|
140 |
+#ifndef XM_LINUX_H
|
|
141 |
+#define XM_LINUX_H
|
|
142 |
+
|
|
143 |
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
|
|
144 |
+
|
|
145 |
+#define HAVE_TERMIOS
|
|
146 |
+
|
|
147 |
+#define NEED_POSIX_SETPGID
|
|
148 |
+
|
|
149 |
+/* Need R_OK etc, but USG isn't defined. */
|
|
150 |
+#include <unistd.h>
|
|
151 |
+
|
|
152 |
+#endif /* #ifndef XM_LINUX_H */
|
|
153 |
diff --git a/gdb/configure.host b/gdb/configure.host
|
|
154 |
index 794eeee..ebc209b 100644
|
|
155 |
--- a/gdb/configure.host
|
|
156 |
+++ b/gdb/configure.host
|
|
157 |
@@ -139,6 +139,7 @@ powerpc64-*-linux*) gdb_host=ppc64-linux
|
|
158 |
|
|
159 |
s390*-*-*) gdb_host=s390 ;;
|
|
160 |
|
|
161 |
+sh*-*-linux*) gdb_host=linux ;;
|
|
162 |
sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu)
|
|
163 |
gdb_host=nbsd ;;
|
|
164 |
sh*-*-openbsd*) gdb_host=nbsd ;;
|
|
165 |
diff --git a/gdb/sh-linux-nat.c b/gdb/sh-linux-nat.c
|
|
166 |
new file mode 100644
|
|
167 |
index 0000000..18e423d
|
|
168 |
--- /dev/null
|
|
169 |
+++ b/gdb/sh-linux-nat.c
|
|
170 |
@@ -0,0 +1,269 @@
|
|
171 |
+/* Low level SH interface to ptrace, for GDB when running native.
|
|
172 |
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
|
173 |
+
|
|
174 |
+This file is part of GDB.
|
|
175 |
+
|
|
176 |
+This program is free software; you can redistribute it and/or modify
|
|
177 |
+it under the terms of the GNU General Public License as published by
|
|
178 |
+the Free Software Foundation; either version 2 of the License, or
|
|
179 |
+(at your option) any later version.
|
|
180 |
+
|
|
181 |
+This program is distributed in the hope that it will be useful,
|
|
182 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
183 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
184 |
+GNU General Public License for more details.
|
|
185 |
+
|
|
186 |
+You should have received a copy of the GNU General Public License
|
|
187 |
+along with this program; if not, write to the Free Software
|
|
188 |
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
189 |
+
|
|
190 |
+#include "defs.h"
|
|
191 |
+#include "inferior.h"
|
|
192 |
+#include "gdbcore.h"
|
|
193 |
+#include "regcache.h"
|
|
194 |
+#include "linux-nat.h"
|
|
195 |
+#include "target.h"
|
|
196 |
+#include "arch-utils.h"
|
|
197 |
+
|
|
198 |
+#include "gdb_assert.h"
|
|
199 |
+#include "gdb_string.h"
|
|
200 |
+#include <sys/ptrace.h>
|
|
201 |
+#include <sys/user.h>
|
|
202 |
+#include <sys/procfs.h>
|
|
203 |
+#include <asm/ptrace.h>
|
|
204 |
+
|
|
205 |
+/* Prototypes for supply_gregset etc. */
|
|
206 |
+#include "gregset.h"
|
|
207 |
+#include "sh-tdep.h"
|
|
208 |
+
|
|
209 |
+/* Defines ps_err_e, struct ps_prochandle. */
|
|
210 |
+#include "gdb_proc_service.h"
|
|
211 |
+
|
|
212 |
+//#include <asm/elf.h>
|
|
213 |
+
|
|
214 |
+#define SH_LINUX_NUM_REGS 40
|
|
215 |
+/* This table must line up with REGISTER_NAME in "sh-tdep.c". */
|
|
216 |
+static const int regmap[] =
|
|
217 |
+{
|
|
218 |
+ /* general registers 0-15 */
|
|
219 |
+ REG_REG0 , REG_REG0+1 , REG_REG0+2 , REG_REG0+3,
|
|
220 |
+ REG_REG0+4 , REG_REG0+5 , REG_REG0+6 , REG_REG0+7,
|
|
221 |
+ REG_REG0+8 , REG_REG0+9 , REG_REG0+10, REG_REG0+11,
|
|
222 |
+ REG_REG0+12, REG_REG0+13, REG_REG0+14, REG_REG0+15,
|
|
223 |
+ /* 16 - 22 */
|
|
224 |
+ REG_PC, REG_PR, REG_GBR, -1, REG_MACH, REG_MACL, REG_SR,
|
|
225 |
+ /* 23, 24 */
|
|
226 |
+ REG_FPUL, REG_FPSCR,
|
|
227 |
+ /* floating point registers 25 - 40 */
|
|
228 |
+ REG_FPREG0 , REG_FPREG0+1 , REG_FPREG0+2 , REG_FPREG0+3 ,
|
|
229 |
+ REG_FPREG0+4 , REG_FPREG0+5 , REG_FPREG0+6 , REG_FPREG0+7 ,
|
|
230 |
+ REG_FPREG0+8 , REG_FPREG0+9 , REG_FPREG0+10, REG_FPREG0+11,
|
|
231 |
+ REG_FPREG0+12, REG_FPREG0+13, REG_FPREG0+14, REG_FPREG0+15,
|
|
232 |
+};
|
|
233 |
+
|
|
234 |
+CORE_ADDR
|
|
235 |
+register_u_addr (CORE_ADDR blockend, int regnum)
|
|
236 |
+{
|
|
237 |
+ if (regnum < 0 || regnum >= sizeof regmap/sizeof regmap[0])
|
|
238 |
+ return (CORE_ADDR)-1;
|
|
239 |
+ return (blockend + 4 * regmap[regnum]);
|
|
240 |
+}
|
|
241 |
+
|
|
242 |
+
|
|
243 |
+/* Return the address in the core dump or inferior of register REGNO.
|
|
244 |
+ BLOCKEND is the address of the end of the user structure. */
|
|
245 |
+
|
|
246 |
+CORE_ADDR
|
|
247 |
+register_addr (int regno, CORE_ADDR blockend)
|
|
248 |
+{
|
|
249 |
+ CORE_ADDR addr;
|
|
250 |
+
|
|
251 |
+ if (regno < 0 || regno >= SH_LINUX_NUM_REGS) {
|
|
252 |
+ internal_error (__FILE__, __LINE__,
|
|
253 |
+ _("Got request for bad register number %d."), regno);
|
|
254 |
+ }
|
|
255 |
+
|
|
256 |
+ REGISTER_U_ADDR (addr, blockend, regno);
|
|
257 |
+
|
|
258 |
+ return addr;
|
|
259 |
+}
|
|
260 |
+
|
|
261 |
+/* Fetch one register. */
|
|
262 |
+
|
|
263 |
+static void
|
|
264 |
+fetch_register (struct regcache *regcache, int tid, int regno)
|
|
265 |
+{
|
|
266 |
+ int val;
|
|
267 |
+
|
|
268 |
+ if (cannot_fetch_register (regno))
|
|
269 |
+ {
|
|
270 |
+ regcache_raw_supply (regcache, regno, NULL);
|
|
271 |
+ return;
|
|
272 |
+ }
|
|
273 |
+
|
|
274 |
+ errno = 0;
|
|
275 |
+ val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
|
|
276 |
+ if (errno != 0)
|
|
277 |
+ perror_with_name (_("Couldn't get registers"));
|
|
278 |
+
|
|
279 |
+ regcache_raw_supply (regcache, regno, &val);
|
|
280 |
+}
|
|
281 |
+
|
|
282 |
+/* Store one register. */
|
|
283 |
+
|
|
284 |
+static void
|
|
285 |
+store_register (struct regcache *regcache, int tid, int regno)
|
|
286 |
+{
|
|
287 |
+ int val;
|
|
288 |
+
|
|
289 |
+ if (cannot_store_register (regno))
|
|
290 |
+ return;
|
|
291 |
+
|
|
292 |
+ errno = 0;
|
|
293 |
+ regcache_raw_collect (regcache, regno, &val);
|
|
294 |
+ ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
|
|
295 |
+ if (errno != 0)
|
|
296 |
+ perror_with_name (_("Couldn't write registers"));
|
|
297 |
+}
|
|
298 |
+
|
|
299 |
+/* Transfering the general-purpose registers between GDB, inferiors
|
|
300 |
+ and core files. */
|
|
301 |
+
|
|
302 |
+/* Fill GDB's register array with the general-purpose register values
|
|
303 |
+ in *GREGSETP. */
|
|
304 |
+
|
|
305 |
+void
|
|
306 |
+supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp)
|
|
307 |
+{
|
|
308 |
+ elf_greg_t *regp = (elf_greg_t *) gregsetp;
|
|
309 |
+ int i;
|
|
310 |
+
|
|
311 |
+ for (i = 0; i < 23; i++)
|
|
312 |
+ if (regmap[i] == -1)
|
|
313 |
+ regcache_raw_supply (regcache, i, NULL);
|
|
314 |
+ else
|
|
315 |
+ regcache_raw_supply (regcache, i, (char *) (regp + regmap[i]));
|
|
316 |
+}
|
|
317 |
+
|
|
318 |
+/* Fill register REGNO (if it is a general-purpose register) in
|
|
319 |
+ *GREGSETPS with the value in GDB's register array. If REGNO is -1,
|
|
320 |
+ do this for all registers. */
|
|
321 |
+
|
|
322 |
+void
|
|
323 |
+fill_gregset (const struct regcache *regcache, elf_gregset_t *gregsetp, int regno)
|
|
324 |
+{
|
|
325 |
+ elf_greg_t *regp = (elf_greg_t *) gregsetp;
|
|
326 |
+ int i;
|
|
327 |
+
|
|
328 |
+ for (i = 0; i < 23; i++)
|
|
329 |
+ if (regmap[i] != -1 && (regno == -1 || regno == i))
|
|
330 |
+ regcache_raw_collect (regcache, i, (char *) (regp + regmap[i]));
|
|
331 |
+}
|
|
332 |
+
|
|
333 |
+/* Transfering floating-point registers between GDB, inferiors and cores. */
|
|
334 |
+
|
|
335 |
+/* Fill GDB's register array with the floating-point register values in
|
|
336 |
+ *FPREGSETP. */
|
|
337 |
+
|
|
338 |
+void
|
|
339 |
+supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
|
|
340 |
+{
|
|
341 |
+ int i;
|
|
342 |
+ long *regp = (long *)fpregsetp;
|
|
343 |
+
|
|
344 |
+ for (i = 0; i < 16; i++)
|
|
345 |
+ regcache_raw_supply (regcache, 25 + i, (char *) (regp + i));
|
|
346 |
+ regcache_raw_supply (regcache, FPUL_REGNUM, (char *) (regp + REG_FPUL - REG_FPREG0));
|
|
347 |
+ regcache_raw_supply (regcache, FPSCR_REGNUM, (char *) (regp + REG_FPSCR - REG_FPREG0));
|
|
348 |
+}
|
|
349 |
+
|
|
350 |
+/* Fill register REGNO (if it is a floating-point register) in
|
|
351 |
+ *FPREGSETP with the value in GDB's register array. If REGNO is -1,
|
|
352 |
+ do this for all registers. */
|
|
353 |
+
|
|
354 |
+void
|
|
355 |
+fill_fpregset (const struct regcache *regcache, elf_fpregset_t *fpregsetp, int regno)
|
|
356 |
+{
|
|
357 |
+ int i;
|
|
358 |
+ long *regp = (long *)fpregsetp;
|
|
359 |
+
|
|
360 |
+ for (i = 0; i < 16; i++)
|
|
361 |
+ if ((regno == -1) || (regno == i))
|
|
362 |
+ regcache_raw_collect (regcache, 25 + i, (char *) (regp + i));
|
|
363 |
+ if ((regno == -1) || regno == FPSCR_REGNUM)
|
|
364 |
+ regcache_raw_collect (regcache, FPSCR_REGNUM, (char *) (regp + REG_FPSCR - REG_FPREG0));
|
|
365 |
+ if ((regno == -1) || regno == FPUL_REGNUM)
|
|
366 |
+ regcache_raw_collect (regcache, FPUL_REGNUM, (char *) (regp + REG_FPUL - REG_FPREG0));
|
|
367 |
+}
|
|
368 |
+
|
|
369 |
+/* Transferring arbitrary registers between GDB and inferior. */
|
|
370 |
+
|
|
371 |
+/* Check if register REGNO in the child process is accessible.
|
|
372 |
+ If we are accessing registers directly via the U area, only the
|
|
373 |
+ general-purpose registers are available.
|
|
374 |
+ All registers should be accessible if we have GETREGS support. */
|
|
375 |
+
|
|
376 |
+int
|
|
377 |
+cannot_fetch_register (int regno)
|
|
378 |
+{
|
|
379 |
+ return (regno < 0 || regno >= sizeof regmap / sizeof regmap[0] || regmap[regno] == -1);
|
|
380 |
+}
|
|
381 |
+
|
|
382 |
+int
|
|
383 |
+cannot_store_register (int regno)
|
|
384 |
+{
|
|
385 |
+ return (regno < 0 || regno >= sizeof regmap / sizeof regmap[0] || regmap[regno] == -1);
|
|
386 |
+}
|
|
387 |
+
|
|
388 |
+/* Fetch register values from the inferior.
|
|
389 |
+ If REGNO is negative, do this for all registers.
|
|
390 |
+ Otherwise, REGNO specifies which register (so we can save time). */
|
|
391 |
+
|
|
392 |
+static void
|
|
393 |
+sh_linux_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno)
|
|
394 |
+{
|
|
395 |
+ int i;
|
|
396 |
+ int tid;
|
|
397 |
+
|
|
398 |
+ /* GNU/Linux LWP ID's are process ID's. */
|
|
399 |
+ if ((tid = TIDGET (inferior_ptid)) == 0)
|
|
400 |
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
|
401 |
+
|
|
402 |
+ for (i = 0; i < SH_LINUX_NUM_REGS; i++)
|
|
403 |
+ if (regno == -1 || regno == i)
|
|
404 |
+ fetch_register (regcache, tid, i);
|
|
405 |
+}
|
|
406 |
+/* Store our register values back into the inferior.
|
|
407 |
+ If REGNO is negative, do this for all registers.
|
|
408 |
+ Otherwise, REGNO specifies which register (so we can save time). */
|
|
409 |
+
|
|
410 |
+static void
|
|
411 |
+sh_linux_store_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno)
|
|
412 |
+{
|
|
413 |
+ int i;
|
|
414 |
+ int tid;
|
|
415 |
+
|
|
416 |
+ /* GNU/Linux LWP ID's are process ID's. */
|
|
417 |
+ if ((tid = TIDGET (inferior_ptid)) == 0)
|
|
418 |
+ tid = PIDGET (inferior_ptid); /* Not a threaded program. */
|
|
419 |
+
|
|
420 |
+ for (i = 0; i < SH_LINUX_NUM_REGS; i++)
|
|
421 |
+ if (regno == -1 || regno == i)
|
|
422 |
+ store_register (regcache, tid, i);
|
|
423 |
+}
|
|
424 |
+
|
|
425 |
+void
|
|
426 |
+_initialize_sh_linux_nat (void)
|
|
427 |
+{
|
|
428 |
+ struct target_ops *t;
|
|
429 |
+
|
|
430 |
+ /* Fill in the generic GNU/Linux methods. */
|
|
431 |
+ t = linux_target ();
|
|
432 |
+
|
|
433 |
+ /* Add our register access methods. */
|
|
434 |
+ t->to_fetch_registers = sh_linux_fetch_inferior_registers;
|
|
435 |
+ t->to_store_registers = sh_linux_store_inferior_registers;
|
|
436 |
+
|
|
437 |
+ /* Register the target. */
|
|
438 |
+ linux_nat_add_target (t);
|
|
439 |
+}
|
|
440 |
diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
|
|
441 |
index da4137b..be95bc9 100644
|
|
442 |
--- a/gdb/sh-linux-tdep.c
|
|
443 |
+++ b/gdb/sh-linux-tdep.c
|
|
444 |
@@ -18,11 +18,34 @@
|
|
445 |
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
446 |
|
|
447 |
#include "defs.h"
|
|
448 |
+#include "gdbcore.h"
|
|
449 |
+#include "frame.h"
|
|
450 |
+#include "frame-base.h"
|
|
451 |
+#include "frame-unwind.h"
|
|
452 |
+#include "dwarf2-frame.h"
|
|
453 |
+#include "value.h"
|
|
454 |
+#include "regcache.h"
|
|
455 |
+#include "inferior.h"
|
|
456 |
#include "osabi.h"
|
|
457 |
|
|
458 |
+#include "reggroups.h"
|
|
459 |
+#include "arch-utils.h"
|
|
460 |
+#include "floatformat.h"
|
|
461 |
#include "solib-svr4.h"
|
|
462 |
#include "symtab.h"
|
|
463 |
+#include "gdb_string.h"
|
|
464 |
+#include "command.h"
|
|
465 |
+#include "gdb_assert.h"
|
|
466 |
|
|
467 |
+#include <sys/ptrace.h>
|
|
468 |
+#include <sys/types.h>
|
|
469 |
+#include <sys/param.h>
|
|
470 |
+#include <sys/user.h>
|
|
471 |
+#include <sys/syscall.h>
|
|
472 |
+
|
|
473 |
+#include <asm/ptrace.h>
|
|
474 |
+
|
|
475 |
+#include "regset.h"
|
|
476 |
#include "glibc-tdep.h"
|
|
477 |
#include "sh-tdep.h"
|
|
478 |
|
|
479 |
@@ -69,9 +92,505 @@ static const struct sh_corefile_regmap fpregs_table[] =
|
|
480 |
{-1 /* Terminator. */, 0}
|
|
481 |
};
|
|
482 |
|
|
483 |
+/* Recognizing signal handler frames. */
|
|
484 |
+
|
|
485 |
+/* GNU/Linux has two flavors of signals. Normal signal handlers, and
|
|
486 |
+ "realtime" (RT) signals. The RT signals can provide additional
|
|
487 |
+ information to the signal handler if the SA_SIGINFO flag is set
|
|
488 |
+ when establishing a signal handler using `sigaction'. It is not
|
|
489 |
+ unlikely that future versions of GNU/Linux will support SA_SIGINFO
|
|
490 |
+ for normal signals too. */
|
|
491 |
+
|
|
492 |
+/* When the SH Linux kernel calls a signal handler and the
|
|
493 |
+ SA_RESTORER flag isn't set, the return address points to a bit of
|
|
494 |
+ code on the stack. This function returns whether the PC appears to
|
|
495 |
+ be within this bit of code.
|
|
496 |
+
|
|
497 |
+ The instruction sequence for normal signals is
|
|
498 |
+ mov.w 1f,r3
|
|
499 |
+ trapa #16
|
|
500 |
+ or r0, r0
|
|
501 |
+ or r0, r0
|
|
502 |
+ or r0, r0
|
|
503 |
+ or r0, r0
|
|
504 |
+ or r0, r0
|
|
505 |
+ 1: .word __NR_sigreturn
|
|
506 |
+ or 0x9305 0xc310 0x200b 0x200b 0x200b 0x200b 0x200b 0x0077.
|
|
507 |
+
|
|
508 |
+ Checking for the code sequence should be somewhat reliable, because
|
|
509 |
+ the effect is to call the system call sigreturn. This is unlikely
|
|
510 |
+ to occur anywhere other than a signal trampoline.
|
|
511 |
+
|
|
512 |
+ It kind of sucks that we have to read memory from the process in
|
|
513 |
+ order to identify a signal trampoline, but there doesn't seem to be
|
|
514 |
+ any other way. The PC_IN_SIGTRAMP macro in tm-linux.h arranges to
|
|
515 |
+ only call us if no function name could be identified, which should
|
|
516 |
+ be the case since the code is on the stack.
|
|
517 |
+
|
|
518 |
+ Detection of signal trampolines for handlers that set the
|
|
519 |
+ SA_RESTORER flag is in general not possible. Unfortunately this is
|
|
520 |
+ what the GNU C Library has been doing for quite some time now.
|
|
521 |
+ However, as of version 2.1.2, the GNU C Library uses signal
|
|
522 |
+ trampolines (named __restore and __restore_rt) that are identical
|
|
523 |
+ to the ones used by the kernel. Therefore, these trampolines are
|
|
524 |
+ supported too. */
|
|
525 |
+
|
|
526 |
+#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
|
|
527 |
+#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */
|
|
528 |
+#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
|
|
529 |
+
|
|
530 |
+#define LINUX_SIGTRAMP_INSN0 MOVW(7) /* Move mem word at PC+7 to R3 */
|
|
531 |
+#define LINUX_SIGTRAMP_INSN1 TRAP16 /* Syscall w/no args (NR in R3) */
|
|
532 |
+#define LINUX_SIGTRAMP_INSN2 OR_R0_R0 /* or r0,r0 (insert to avoid hardware bug) */
|
|
533 |
+
|
|
534 |
+static const unsigned short linux_sigtramp_code[] =
|
|
535 |
+{
|
|
536 |
+ LINUX_SIGTRAMP_INSN0,
|
|
537 |
+ LINUX_SIGTRAMP_INSN1,
|
|
538 |
+ LINUX_SIGTRAMP_INSN2,
|
|
539 |
+ LINUX_SIGTRAMP_INSN2,
|
|
540 |
+ LINUX_SIGTRAMP_INSN2,
|
|
541 |
+ LINUX_SIGTRAMP_INSN2,
|
|
542 |
+ LINUX_SIGTRAMP_INSN2,
|
|
543 |
+ __NR_sigreturn
|
|
544 |
+};
|
|
545 |
+
|
|
546 |
+#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
|
|
547 |
+
|
|
548 |
+/* If PC is in a sigtramp routine, return the address of the start of
|
|
549 |
+ the routine. Otherwise, return 0. */
|
|
550 |
+
|
|
551 |
+static CORE_ADDR
|
|
552 |
+sh_linux_sigtramp_start (struct frame_info *next_frame)
|
|
553 |
+{
|
|
554 |
+ CORE_ADDR pc = get_frame_pc (next_frame);
|
|
555 |
+ gdb_byte buf[LINUX_SIGTRAMP_LEN];
|
|
556 |
+
|
|
557 |
+ /* We only recognize a signal trampoline if PC is at the start of
|
|
558 |
+ one of the three instructions. We optimize for finding the PC at
|
|
559 |
+ the start, as will be the case when the trampoline is not the
|
|
560 |
+ first frame on the stack. We assume that in the case where the
|
|
561 |
+ PC is not at the start of the instruction sequence, there will be
|
|
562 |
+ a few trailing readable bytes on the stack. */
|
|
563 |
+
|
|
564 |
+ if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
|
|
565 |
+ return 0;
|
|
566 |
+
|
|
567 |
+ if (buf[0] != LINUX_SIGTRAMP_INSN0)
|
|
568 |
+ {
|
|
569 |
+ if (buf[0] != LINUX_SIGTRAMP_INSN1)
|
|
570 |
+ return 0;
|
|
571 |
+
|
|
572 |
+ pc -= 2;
|
|
573 |
+
|
|
574 |
+ if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
|
|
575 |
+ return 0;
|
|
576 |
+ }
|
|
577 |
+
|
|
578 |
+ if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
|
|
579 |
+ return 0;
|
|
580 |
+
|
|
581 |
+ return pc;
|
|
582 |
+}
|
|
583 |
+
|
|
584 |
+/* This function does the same for RT signals. Here the instruction
|
|
585 |
+ sequence is
|
|
586 |
+ mov.w 1f,r3
|
|
587 |
+ trapa #16
|
|
588 |
+ or r0, r0
|
|
589 |
+ or r0, r0
|
|
590 |
+ or r0, r0
|
|
591 |
+ or r0, r0
|
|
592 |
+ or r0, r0
|
|
593 |
+ 1: .word __NR_rt_sigreturn
|
|
594 |
+ or 0x9305 0xc310 0x200b 0x200b 0x200b 0x200b 0x200b 0x00ad.
|
|
595 |
+
|
|
596 |
+ The effect is to call the system call rt_sigreturn. */
|
|
597 |
+
|
|
598 |
+#define LINUX_RT_SIGTRAMP_INSN0 MOVW(7) /* Move mem word at PC+7 to R3 */
|
|
599 |
+#define LINUX_RT_SIGTRAMP_INSN1 TRAP16 /* Syscall w/no args (NR in R3) */
|
|
600 |
+#define LINUX_RT_SIGTRAMP_INSN2 OR_R0_R0 /* or r0,r0 (insert to avoid hardware bug) */
|
|
601 |
+
|
|
602 |
+static const unsigned short linux_rt_sigtramp_code[] =
|
|
603 |
+{
|
|
604 |
+ LINUX_RT_SIGTRAMP_INSN0,
|
|
605 |
+ LINUX_RT_SIGTRAMP_INSN1,
|
|
606 |
+ LINUX_RT_SIGTRAMP_INSN2,
|
|
607 |
+ LINUX_RT_SIGTRAMP_INSN2,
|
|
608 |
+ LINUX_RT_SIGTRAMP_INSN2,
|
|
609 |
+ LINUX_RT_SIGTRAMP_INSN2,
|
|
610 |
+ LINUX_RT_SIGTRAMP_INSN2,
|
|
611 |
+ __NR_rt_sigreturn
|
|
612 |
+};
|
|
613 |
+
|
|
614 |
+#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
|
|
615 |
+
|
|
616 |
+/* If PC is in a RT sigtramp routine, return the address of the start
|
|
617 |
+ of the routine. Otherwise, return 0. */
|
|
618 |
+
|
|
619 |
+static CORE_ADDR
|
|
620 |
+sh_linux_rt_sigtramp_start (struct frame_info *next_frame)
|
|
621 |
+{
|
|
622 |
+ CORE_ADDR pc = get_frame_pc (next_frame);
|
|
623 |
+ gdb_byte buf[LINUX_RT_SIGTRAMP_LEN];
|
|
624 |
+
|
|
625 |
+ /* We only recognize a signal trampoline if PC is at the start of
|
|
626 |
+ one of the two instructions. We optimize for finding the PC at
|
|
627 |
+ the start, as will be the case when the trampoline is not the
|
|
628 |
+ first frame on the stack. We assume that in the case where the
|
|
629 |
+ PC is not at the start of the instruction sequence, there will be
|
|
630 |
+ a few trailing readable bytes on the stack. */
|
|
631 |
+
|
|
632 |
+ if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
|
|
633 |
+ return 0;
|
|
634 |
+
|
|
635 |
+ if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
|
|
636 |
+ {
|
|
637 |
+ if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
|
|
638 |
+ return 0;
|
|
639 |
+
|
|
640 |
+ pc -= 2;
|
|
641 |
+
|
|
642 |
+ if (!safe_frame_unwind_memory (next_frame, pc, buf,
|
|
643 |
+ LINUX_RT_SIGTRAMP_LEN))
|
|
644 |
+ return 0;
|
|
645 |
+ }
|
|
646 |
+
|
|
647 |
+ if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
|
|
648 |
+ return 0;
|
|
649 |
+
|
|
650 |
+ return pc;
|
|
651 |
+}
|
|
652 |
+
|
|
653 |
+/* Return whether PC is in a GNU/Linux sigtramp routine. */
|
|
654 |
+
|
|
655 |
+static int
|
|
656 |
+sh_linux_sigtramp_p (struct frame_info *this_frame)
|
|
657 |
+{
|
|
658 |
+ CORE_ADDR pc = get_frame_pc (this_frame);
|
|
659 |
+ char *name;
|
|
660 |
+
|
|
661 |
+ find_pc_partial_function (pc, &name, NULL, NULL);
|
|
662 |
+
|
|
663 |
+ /* If we have NAME, we can optimize the search. The trampolines are
|
|
664 |
+ named __restore and __restore_rt. However, they aren't dynamically
|
|
665 |
+ exported from the shared C library, so the trampoline may appear to
|
|
666 |
+ be part of the preceding function. This should always be sigaction,
|
|
667 |
+ __sigaction, or __libc_sigaction (all aliases to the same function). */
|
|
668 |
+ if (name == NULL || strstr (name, "sigaction") != NULL)
|
|
669 |
+ return (sh_linux_sigtramp_start (this_frame) != 0
|
|
670 |
+ || sh_linux_rt_sigtramp_start (this_frame) != 0);
|
|
671 |
+
|
|
672 |
+ return (strcmp ("__restore", name) == 0
|
|
673 |
+ || strcmp ("__restore_rt", name) == 0);
|
|
674 |
+}
|
|
675 |
+
|
|
676 |
+/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
|
|
677 |
+#define SH_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 12
|
|
678 |
+
|
|
679 |
+
|
|
680 |
+/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
|
|
681 |
+ routine, return the address of the associated sigcontext structure. */
|
|
682 |
+
|
|
683 |
+static CORE_ADDR
|
|
684 |
+sh_linux_sigcontext_addr (struct frame_info *this_frame)
|
|
685 |
+{
|
|
686 |
+ CORE_ADDR pc;
|
|
687 |
+ CORE_ADDR sp;
|
|
688 |
+
|
|
689 |
+ sp = get_frame_register_unsigned (this_frame, SP_REGNUM);
|
|
690 |
+
|
|
691 |
+ pc = sh_linux_sigtramp_start (this_frame);
|
|
692 |
+ if (pc)
|
|
693 |
+ {
|
|
694 |
+ return sp;
|
|
695 |
+ }
|
|
696 |
+
|
|
697 |
+ pc = sh_linux_rt_sigtramp_start (this_frame);
|
|
698 |
+ if (pc)
|
|
699 |
+ {
|
|
700 |
+ CORE_ADDR ucontext_addr;
|
|
701 |
+
|
|
702 |
+ /* The sigcontext structure is part of the user context. A
|
|
703 |
+ pointer to the user context is passed as the third argument
|
|
704 |
+ to the signal handler. */
|
|
705 |
+ ucontext_addr = get_frame_register_unsigned (this_frame, ARG0_REGNUM+2);
|
|
706 |
+ return ucontext_addr + SH_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
|
|
707 |
+ }
|
|
708 |
+
|
|
709 |
+ error ("Couldn't recognize signal trampoline.");
|
|
710 |
+ return 0;
|
|
711 |
+}
|
|
712 |
+
|
|
713 |
+/* Signal trampolines. */
|
|
714 |
+extern struct sh_frame_cache *sh_alloc_frame_cache (void);
|
|
715 |
+
|
|
716 |
+static struct sh_frame_cache *
|
|
717 |
+sh_linux_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
|
|
718 |
+{
|
|
719 |
+ struct sh_frame_cache *cache;
|
|
720 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_current_arch ());
|
|
721 |
+ CORE_ADDR sigcontext_addr;
|
|
722 |
+
|
|
723 |
+ if (*this_cache)
|
|
724 |
+ return *this_cache;
|
|
725 |
+
|
|
726 |
+ cache = sh_alloc_frame_cache ();
|
|
727 |
+
|
|
728 |
+ cache->base = get_frame_register_unsigned (this_frame, SP_REGNUM);
|
|
729 |
+ sigcontext_addr = tdep->sigcontext_addr (this_frame);
|
|
730 |
+ if (tdep->sc_reg_offset)
|
|
731 |
+ {
|
|
732 |
+ int i;
|
|
733 |
+
|
|
734 |
+ gdb_assert (tdep->sc_num_regs <= SH_NUM_REGS);
|
|
735 |
+
|
|
736 |
+ for (i = 0; i < tdep->sc_num_regs; i++)
|
|
737 |
+ if (tdep->sc_reg_offset[i] != -1)
|
|
738 |
+ cache->saved_regs[i] = sigcontext_addr + tdep->sc_reg_offset[i];
|
|
739 |
+ }
|
|
740 |
+
|
|
741 |
+ *this_cache = cache;
|
|
742 |
+ return cache;
|
|
743 |
+}
|
|
744 |
+
|
|
745 |
+static void
|
|
746 |
+sh_linux_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
|
|
747 |
+ struct frame_id *this_id)
|
|
748 |
+{
|
|
749 |
+ struct sh_frame_cache *cache =
|
|
750 |
+ sh_linux_sigtramp_frame_cache (this_frame, this_cache);
|
|
751 |
+
|
|
752 |
+ (*this_id) = frame_id_build (cache->base + 64, cache->pc);
|
|
753 |
+}
|
|
754 |
+
|
|
755 |
+extern struct value * sh_frame_prev_register ();
|
|
756 |
+static struct value *
|
|
757 |
+sh_linux_sigtramp_frame_prev_register (struct frame_info *this_frame,
|
|
758 |
+ void **this_cache, int regnum)
|
|
759 |
+{
|
|
760 |
+ sh_linux_sigtramp_frame_cache (this_frame, this_cache);
|
|
761 |
+
|
|
762 |
+ return sh_frame_prev_register (this_frame, this_cache, regnum);
|
|
763 |
+}
|
|
764 |
+
|
|
765 |
+static int
|
|
766 |
+sh_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
|
|
767 |
+ struct frame_info *this_frame,
|
|
768 |
+ void **this_prologue_cache)
|
|
769 |
+{
|
|
770 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
|
|
771 |
+
|
|
772 |
+ /* We shouldn't even bother if we don't have a sigcontext_addr
|
|
773 |
+ handler. */
|
|
774 |
+ if (tdep->sigcontext_addr == NULL)
|
|
775 |
+ return 0;
|
|
776 |
+
|
|
777 |
+ if (tdep->sigtramp_p != NULL)
|
|
778 |
+ {
|
|
779 |
+ if (tdep->sigtramp_p (this_frame))
|
|
780 |
+ return 1;
|
|
781 |
+ }
|
|
782 |
+
|
|
783 |
+ return 0;
|
|
784 |
+}
|
|
785 |
+
|
|
786 |
+static const struct frame_unwind sh_linux_sigtramp_frame_unwind =
|
|
787 |
+{
|
|
788 |
+ SIGTRAMP_FRAME,
|
|
789 |
+ sh_linux_sigtramp_frame_this_id,
|
|
790 |
+ sh_linux_sigtramp_frame_prev_register,
|
|
791 |
+ NULL,
|
|
792 |
+ sh_linux_sigtramp_frame_sniffer
|
|
793 |
+};
|
|
794 |
+
|
|
795 |
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
|
|
796 |
+ in the general-purpose register set REGSET to register cache
|
|
797 |
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
798 |
+
|
|
799 |
+void
|
|
800 |
+sh_supply_gregset (const struct regset *regset, struct regcache *regcache,
|
|
801 |
+ int regnum, const void *gregs, size_t len)
|
|
802 |
+{
|
|
803 |
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
|
|
804 |
+ const char *regs = gregs;
|
|
805 |
+ int i;
|
|
806 |
+
|
|
807 |
+ gdb_assert (len == tdep->sizeof_gregset);
|
|
808 |
+
|
|
809 |
+ for (i = 0; i < tdep->gregset_num_regs; i++)
|
|
810 |
+ {
|
|
811 |
+ if ((regnum == i || regnum == -1)
|
|
812 |
+ && tdep->gregset_reg_offset[i] != -1)
|
|
813 |
+ regcache_raw_supply (regcache, i, regs + tdep->gregset_reg_offset[i]);
|
|
814 |
+ }
|
|
815 |
+}
|
|
816 |
+
|
|
817 |
+/* Collect register REGNUM from the register cache REGCACHE and store
|
|
818 |
+ it in the buffer specified by GREGS and LEN as described by the
|
|
819 |
+ general-purpose register set REGSET. If REGNUM is -1, do this for
|
|
820 |
+ all registers in REGSET. */
|
|
821 |
+
|
|
822 |
+void
|
|
823 |
+sh_collect_gregset (const struct regset *regset,
|
|
824 |
+ const struct regcache *regcache,
|
|
825 |
+ int regnum, void *gregs, size_t len)
|
|
826 |
+{
|
|
827 |
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
|
|
828 |
+ char *regs = gregs;
|
|
829 |
+ int i;
|
|
830 |
+
|
|
831 |
+ gdb_assert (len == tdep->sizeof_gregset);
|
|
832 |
+
|
|
833 |
+ for (i = 0; i < tdep->gregset_num_regs; i++)
|
|
834 |
+ {
|
|
835 |
+ if ((regnum == i || regnum == -1)
|
|
836 |
+ && tdep->gregset_reg_offset[i] != -1)
|
|
837 |
+ regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
|
|
838 |
+ }
|
|
839 |
+}
|
|
840 |
+
|
|
841 |
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
|
|
842 |
+ in the floating-point register set REGSET to register cache
|
|
843 |
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
844 |
+
|
|
845 |
+static void
|
|
846 |
+sh_supply_fpregset (const struct regset *regset, struct regcache *regcache,
|
|
847 |
+ int regnum, const void *fpregs, size_t len)
|
|
848 |
+{
|
|
849 |
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
|
|
850 |
+ const char *regs = fpregs;
|
|
851 |
+ int i;
|
|
852 |
+
|
|
853 |
+ gdb_assert (len == tdep->sizeof_fpregset);
|
|
854 |
+ for (i = 0; i < 16; i++)
|
|
855 |
+ {
|
|
856 |
+ if (regnum == i+25 || regnum == -1)
|
|
857 |
+ regcache_raw_supply (regcache, i+25, regs + i*4);
|
|
858 |
+ }
|
|
859 |
+ if (regnum == FPSCR_REGNUM || regnum == -1)
|
|
860 |
+ regcache_raw_supply (regcache, FPSCR_REGNUM, regs + 32*4);
|
|
861 |
+ if (regnum == FPUL_REGNUM || regnum == -1)
|
|
862 |
+ regcache_raw_supply (regcache, FPUL_REGNUM, regs + 33*4);
|
|
863 |
+}
|
|
864 |
+
|
|
865 |
+/* Collect register REGNUM from the register cache REGCACHE and store
|
|
866 |
+ it in the buffer specified by FPREGS and LEN as described by the
|
|
867 |
+ floating-point register set REGSET. If REGNUM is -1, do this for
|
|
868 |
+ all registers in REGSET. */
|
|
869 |
+
|
|
870 |
+static void
|
|
871 |
+sh_collect_fpregset (const struct regset *regset,
|
|
872 |
+ const struct regcache *regcache,
|
|
873 |
+ int regnum, void *fpregs, size_t len)
|
|
874 |
+{
|
|
875 |
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
|
|
876 |
+ char *regs = fpregs;
|
|
877 |
+ int i;
|
|
878 |
+
|
|
879 |
+ gdb_assert (len == tdep->sizeof_fpregset);
|
|
880 |
+ for (i = 0; i < 16; i++)
|
|
881 |
+ {
|
|
882 |
+ if (regnum == i+25 || regnum == -1)
|
|
883 |
+ regcache_raw_collect (regcache, i+25, regs + i*4);
|
|
884 |
+ }
|
|
885 |
+ if (regnum == FPSCR_REGNUM || regnum == -1)
|
|
886 |
+ regcache_raw_collect (regcache, FPSCR_REGNUM, regs + 32*4);
|
|
887 |
+ if (regnum == FPUL_REGNUM || regnum == -1)
|
|
888 |
+ regcache_raw_collect (regcache, FPUL_REGNUM, regs + 33*4);
|
|
889 |
+}
|
|
890 |
+
|
|
891 |
+/* Return the appropriate register set for the core section identified
|
|
892 |
+ by SECT_NAME and SECT_SIZE. */
|
|
893 |
+
|
|
894 |
+const struct regset *
|
|
895 |
+sh_linux_regset_from_core_section (struct gdbarch *gdbarch,
|
|
896 |
+ const char *sect_name, size_t sect_size)
|
|
897 |
+{
|
|
898 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
899 |
+
|
|
900 |
+ if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
|
|
901 |
+ {
|
|
902 |
+ if (tdep->gregset == NULL)
|
|
903 |
+ tdep->gregset = regset_alloc (gdbarch, sh_supply_gregset,
|
|
904 |
+ sh_collect_gregset);
|
|
905 |
+ return tdep->gregset;
|
|
906 |
+ }
|
|
907 |
+
|
|
908 |
+ if ((strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset))
|
|
909 |
+ {
|
|
910 |
+ if (tdep->fpregset == NULL)
|
|
911 |
+ tdep->fpregset = regset_alloc (gdbarch, sh_supply_fpregset,
|
|
912 |
+ sh_collect_fpregset);
|
|
913 |
+ return tdep->fpregset;
|
|
914 |
+ }
|
|
915 |
+
|
|
916 |
+ return NULL;
|
|
917 |
+}
|
|
918 |
+
|
|
919 |
+/* The register sets used in GNU/Linux ELF core-dumps are identical to
|
|
920 |
+ the register sets in `struct user' that are used for a.out
|
|
921 |
+ core-dumps. These are also used by ptrace(2). The corresponding
|
|
922 |
+ types are `elf_gregset_t' for the general-purpose registers (with
|
|
923 |
+ `elf_greg_t' the type of a single GP register) and `elf_fpregset_t'
|
|
924 |
+ for the floating-point registers.
|
|
925 |
+
|
|
926 |
+ Those types used to be available under the names `gregset_t' and
|
|
927 |
+ `fpregset_t' too, and GDB used those names in the past. But those
|
|
928 |
+ names are now used for the register sets used in the `mcontext_t'
|
|
929 |
+ type, which have a different size and layout. */
|
|
930 |
+
|
|
931 |
+/* Mapping between the general-purpose registers in `struct user'
|
|
932 |
+ format and GDB's register cache layout. */
|
|
933 |
+
|
|
934 |
+/* From <sys/reg.h>. */
|
|
935 |
+static int sh_linux_gregset_reg_offset[] =
|
|
936 |
+{
|
|
937 |
+ 0, 4, 8, 12, 16, 20, 24, 28,
|
|
938 |
+ 32, 36, 40, 44, 48, 52, 56, 60,
|
|
939 |
+
|
|
940 |
+ REG_PC*4, REG_PR*4, REG_GBR*4, -1,
|
|
941 |
+ REG_MACH*4, REG_MACL*4, REG_SR*4,
|
|
942 |
+};
|
|
943 |
+
|
|
944 |
+/* Mapping between the general-purpose registers in `struct
|
|
945 |
+ sigcontext' format and GDB's register cache layout. */
|
|
946 |
+
|
|
947 |
+/* From <asm/sigcontext.h>. */
|
|
948 |
+static int sh_linux_sc_reg_offset[] =
|
|
949 |
+{
|
|
950 |
+ 4, 8, 12, 16, 20, 24, 28, 32,
|
|
951 |
+ 36, 40, 44, 48, 52, 56, 60, 64,
|
|
952 |
+ 68, 72, 80, -1,
|
|
953 |
+ 84, 88, 76
|
|
954 |
+};
|
|
955 |
+
|
|
956 |
static void
|
|
957 |
sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
958 |
{
|
|
959 |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
960 |
+ bfd abfd;
|
|
961 |
+
|
|
962 |
+ tdep->gregset_reg_offset = sh_linux_gregset_reg_offset;
|
|
963 |
+ tdep->gregset_num_regs = ARRAY_SIZE (sh_linux_gregset_reg_offset);
|
|
964 |
+ tdep->sizeof_gregset = 23 * 4;
|
|
965 |
+
|
|
966 |
+ tdep->jb_pc_offset = 32; /* From <bits/setjmp.h>. */
|
|
967 |
+
|
|
968 |
+ tdep->sigtramp_p = sh_linux_sigtramp_p;
|
|
969 |
+ tdep->sigcontext_addr = sh_linux_sigcontext_addr;
|
|
970 |
+ tdep->sc_reg_offset = sh_linux_sc_reg_offset;
|
|
971 |
+ tdep->sc_num_regs = ARRAY_SIZE (sh_linux_sc_reg_offset);
|
|
972 |
+
|
|
973 |
+ frame_unwind_append_unwinder(gdbarch, &sh_linux_sigtramp_frame_unwind);
|
|
974 |
+
|
|
975 |
+ /* If we have a register mapping, enable the generic core file
|
|
976 |
+ support, unless it has already been enabled. */
|
|
977 |
+ if (tdep->gregset_reg_offset
|
|
978 |
+ && !gdbarch_regset_from_core_section_p (gdbarch))
|
|
979 |
+ set_gdbarch_regset_from_core_section (gdbarch,
|
|
980 |
+ sh_linux_regset_from_core_section);
|
|
981 |
+
|
|
982 |
/* GNU/Linux uses SVR4-style shared libraries. */
|
|
983 |
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
|
|
984 |
set_solib_svr4_fetch_link_map_offsets
|
|
985 |
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
|
|
986 |
index 7e01469..735cc84 100644
|
|
987 |
--- a/gdb/sh-tdep.c
|
|
988 |
+++ b/gdb/sh-tdep.c
|
|
989 |
@@ -24,6 +24,9 @@
|
|
990 |
*/
|
|
991 |
|
|
992 |
#include "defs.h"
|
|
993 |
+#include "arch-utils.h"
|
|
994 |
+#include "command.h"
|
|
995 |
+#include "dummy-frame.h"
|
|
996 |
#include "frame.h"
|
|
997 |
#include "frame-base.h"
|
|
998 |
#include "frame-unwind.h"
|
|
999 |
@@ -40,6 +43,7 @@
|
|
1000 |
#include "arch-utils.h"
|
|
1001 |
#include "floatformat.h"
|
|
1002 |
#include "regcache.h"
|
|
1003 |
+#include "regset.h"
|
|
1004 |
#include "doublest.h"
|
|
1005 |
#include "osabi.h"
|
|
1006 |
#include "reggroups.h"
|
|
1007 |
@@ -72,23 +76,6 @@ static const char *sh_active_calling_convention = sh_cc_gcc;
|
|
1008 |
|
|
1009 |
static void (*sh_show_regs) (struct frame_info *);
|
|
1010 |
|
|
1011 |
-#define SH_NUM_REGS 67
|
|
1012 |
-
|
|
1013 |
-struct sh_frame_cache
|
|
1014 |
-{
|
|
1015 |
- /* Base address. */
|
|
1016 |
- CORE_ADDR base;
|
|
1017 |
- LONGEST sp_offset;
|
|
1018 |
- CORE_ADDR pc;
|
|
1019 |
-
|
|
1020 |
- /* Flag showing that a frame has been created in the prologue code. */
|
|
1021 |
- int uses_fp;
|
|
1022 |
-
|
|
1023 |
- /* Saved registers. */
|
|
1024 |
- CORE_ADDR saved_regs[SH_NUM_REGS];
|
|
1025 |
- CORE_ADDR saved_sp;
|
|
1026 |
-};
|
|
1027 |
-
|
|
1028 |
static int
|
|
1029 |
sh_is_renesas_calling_convention (struct type *func_type)
|
|
1030 |
{
|
|
1031 |
@@ -1045,7 +1032,7 @@ sh_treat_as_flt_p (struct type *type)
|
|
1032 |
return 0;
|
|
1033 |
/* Otherwise if the type of that member is float, the whole type is
|
|
1034 |
treated as float. */
|
|
1035 |
- if (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT)
|
|
1036 |
+ if (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 0))) == TYPE_CODE_FLT)
|
|
1037 |
return 1;
|
|
1038 |
/* Otherwise it's not treated as float. */
|
|
1039 |
return 0;
|
|
1040 |
@@ -1095,7 +1082,7 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
|
|
1041 |
in four registers available. Loop thru args from first to last. */
|
|
1042 |
for (argnum = 0; argnum < nargs; argnum++)
|
|
1043 |
{
|
|
1044 |
- type = value_type (args[argnum]);
|
|
1045 |
+ type = check_typedef (value_type (args[argnum]));
|
|
1046 |
len = TYPE_LENGTH (type);
|
|
1047 |
val = sh_justify_value_in_reg (gdbarch, args[argnum], len);
|
|
1048 |
|
|
1049 |
@@ -2485,7 +2472,7 @@ sh_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
|
|
1050 |
reg->how = DWARF2_FRAME_REG_UNDEFINED;
|
|
1051 |
}
|
|
1052 |
|
|
1053 |
-static struct sh_frame_cache *
|
|
1054 |
+struct sh_frame_cache *
|
|
1055 |
sh_alloc_frame_cache (void)
|
|
1056 |
{
|
|
1057 |
struct sh_frame_cache *cache;
|
|
1058 |
@@ -2512,7 +2499,7 @@ sh_alloc_frame_cache (void)
|
|
1059 |
return cache;
|
|
1060 |
}
|
|
1061 |
|
|
1062 |
-static struct sh_frame_cache *
|
|
1063 |
+struct sh_frame_cache *
|
|
1064 |
sh_frame_cache (struct frame_info *this_frame, void **this_cache)
|
|
1065 |
{
|
|
1066 |
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
1067 |
@@ -2570,9 +2557,9 @@ sh_frame_cache (struct frame_info *this_frame, void **this_cache)
|
|
1068 |
return cache;
|
|
1069 |
}
|
|
1070 |
|
|
1071 |
-static struct value *
|
|
1072 |
-sh_frame_prev_register (struct frame_info *this_frame,
|
|
1073 |
- void **this_cache, int regnum)
|
|
1074 |
+struct value *
|
|
1075 |
+sh_frame_prev_register (struct frame_info *this_frame, void **this_cache,
|
|
1076 |
+ int regnum)
|
|
1077 |
{
|
|
1078 |
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
1079 |
struct sh_frame_cache *cache = sh_frame_cache (this_frame, this_cache);
|
|
1080 |
@@ -2586,7 +2573,7 @@ sh_frame_prev_register (struct frame_info *this_frame,
|
|
1081 |
the current frame. Frob regnum so that we pull the value from
|
|
1082 |
the correct place. */
|
|
1083 |
if (regnum == gdbarch_pc_regnum (gdbarch))
|
|
1084 |
- regnum = PR_REGNUM;
|
|
1085 |
+ regnum = PR_REGNUM; /* XXX: really? */
|
|
1086 |
|
|
1087 |
if (regnum < SH_NUM_REGS && cache->saved_regs[regnum] != -1)
|
|
1088 |
return frame_unwind_got_memory (this_frame, regnum,
|
|
1089 |
@@ -2829,8 +2816,8 @@ sh_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name,
|
|
1090 |
static struct gdbarch *
|
|
1091 |
sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|
1092 |
{
|
|
1093 |
- struct gdbarch *gdbarch;
|
|
1094 |
struct gdbarch_tdep *tdep;
|
|
1095 |
+ struct gdbarch *gdbarch;
|
|
1096 |
|
|
1097 |
sh_show_regs = sh_generic_show_regs;
|
|
1098 |
switch (info.bfd_arch_info->mach)
|
|
1099 |
@@ -2893,6 +2880,18 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|
1100 |
tdep = XZALLOC (struct gdbarch_tdep);
|
|
1101 |
gdbarch = gdbarch_alloc (&info, tdep);
|
|
1102 |
|
|
1103 |
+ /* General-purpose registers. */
|
|
1104 |
+ tdep->gregset = NULL;
|
|
1105 |
+ tdep->gregset_reg_offset = NULL;
|
|
1106 |
+ tdep->gregset_num_regs = 23;
|
|
1107 |
+ tdep->sizeof_gregset = 0;
|
|
1108 |
+
|
|
1109 |
+ /* Floating-point registers. */
|
|
1110 |
+ tdep->fpregset = NULL;
|
|
1111 |
+ tdep->sizeof_fpregset = 34*4;
|
|
1112 |
+
|
|
1113 |
+ tdep->jb_pc_offset = -1;
|
|
1114 |
+
|
|
1115 |
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
|
|
1116 |
set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
|
|
1117 |
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
|
|
1118 |
@@ -3038,10 +3037,11 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
|
1119 |
break;
|
|
1120 |
}
|
|
1121 |
|
|
1122 |
+ dwarf2_append_unwinders (gdbarch);
|
|
1123 |
+
|
|
1124 |
/* Hook in ABI-specific overrides, if they have been registered. */
|
|
1125 |
gdbarch_init_osabi (info, gdbarch);
|
|
1126 |
|
|
1127 |
- dwarf2_append_unwinders (gdbarch);
|
|
1128 |
frame_unwind_append_unwinder (gdbarch, &sh_frame_unwind);
|
|
1129 |
|
|
1130 |
return gdbarch;
|
|
1131 |
diff --git a/gdb/sh-tdep.h b/gdb/sh-tdep.h
|
|
1132 |
index b53d412..f2bea7d 100644
|
|
1133 |
--- a/gdb/sh-tdep.h
|
|
1134 |
+++ b/gdb/sh-tdep.h
|
|
1135 |
@@ -22,6 +22,12 @@
|
|
1136 |
|
|
1137 |
/* Contributed by Steve Chamberlain sac@cygnus.com */
|
|
1138 |
|
|
1139 |
+struct frame_info;
|
|
1140 |
+struct gdbarch;
|
|
1141 |
+struct reggroup;
|
|
1142 |
+struct regset;
|
|
1143 |
+struct regcache;
|
|
1144 |
+
|
|
1145 |
/* Registers for all SH variants. Used also by sh3-rom.c. */
|
|
1146 |
enum
|
|
1147 |
{
|
|
1148 |
@@ -30,6 +36,7 @@ enum
|
|
1149 |
ARG0_REGNUM = 4,
|
|
1150 |
ARGLAST_REGNUM = 7,
|
|
1151 |
FP_REGNUM = 14,
|
|
1152 |
+ SP_REGNUM = 15,
|
|
1153 |
PC_REGNUM = 16,
|
|
1154 |
PR_REGNUM = 17,
|
|
1155 |
GBR_REGNUM = 18,
|
|
1156 |
@@ -83,8 +90,26 @@ enum
|
|
1157 |
FV_LAST_REGNUM = 79
|
|
1158 |
};
|
|
1159 |
|
|
1160 |
+#define SH_NUM_REGS 67
|
|
1161 |
+
|
|
1162 |
+struct sh_frame_cache
|
|
1163 |
+{
|
|
1164 |
+ /* Base address. */
|
|
1165 |
+ CORE_ADDR base;
|
|
1166 |
+ LONGEST sp_offset;
|
|
1167 |
+ CORE_ADDR pc;
|
|
1168 |
+
|
|
1169 |
+ /* Flag showing that a frame has been created in the prologue code. */
|
|
1170 |
+ int uses_fp;
|
|
1171 |
+
|
|
1172 |
+ /* Saved registers. */
|
|
1173 |
+ CORE_ADDR saved_regs[SH_NUM_REGS];
|
|
1174 |
+ CORE_ADDR saved_sp;
|
|
1175 |
+};
|
|
1176 |
+
|
|
1177 |
extern gdbarch_init_ftype sh64_gdbarch_init;
|
|
1178 |
extern void sh64_show_regs (struct frame_info *);
|
|
1179 |
+extern struct sh_frame_cache *sh_frame_cache (struct frame_info *next_frame, void **this_cache);
|
|
1180 |
|
|
1181 |
/* This structure describes a register in a core-file. */
|
|
1182 |
struct sh_corefile_regmap
|
|
1183 |
@@ -93,8 +118,32 @@ struct sh_corefile_regmap
|
|
1184 |
unsigned int offset;
|
|
1185 |
};
|
|
1186 |
|
|
1187 |
+/* sh architecture specific information. */
|
|
1188 |
struct gdbarch_tdep
|
|
1189 |
{
|
|
1190 |
+ /* General-purpose registers. */
|
|
1191 |
+ struct regset *gregset;
|
|
1192 |
+ int *gregset_reg_offset;
|
|
1193 |
+ int gregset_num_regs;
|
|
1194 |
+ size_t sizeof_gregset;
|
|
1195 |
+
|
|
1196 |
+ /* Floating-point registers. */
|
|
1197 |
+ struct regset *fpregset;
|
|
1198 |
+ size_t sizeof_fpregset;
|
|
1199 |
+
|
|
1200 |
+ /* Offset of saved PC in jmp_buf. */
|
|
1201 |
+ int jb_pc_offset;
|
|
1202 |
+
|
|
1203 |
+ /* Detect sigtramp. */
|
|
1204 |
+ int (*sigtramp_p) (struct frame_info *);
|
|
1205 |
+
|
|
1206 |
+ /* Get address of sigcontext for sigtramp. */
|
|
1207 |
+ CORE_ADDR (*sigcontext_addr) (struct frame_info *);
|
|
1208 |
+
|
|
1209 |
+ /* Offset of registers in `struct sigcontext'. */
|
|
1210 |
+ int *sc_reg_offset;
|
|
1211 |
+ int sc_num_regs;
|
|
1212 |
+
|
|
1213 |
/* Non-NULL when debugging from a core file. Provides the offset
|
|
1214 |
where each general-purpose register is stored inside the associated
|
|
1215 |
core file section. */
|
|
1216 |
diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp
|
|
1217 |
index 615182f..dd5ae09 100644
|
|
1218 |
--- a/gdb/testsuite/gdb.asm/asm-source.exp
|
|
1219 |
+++ b/gdb/testsuite/gdb.asm/asm-source.exp
|
|
1220 |
@@ -105,6 +105,11 @@ switch -glob -- [istarget] {
|
|
1221 |
"powerpc*-*" {
|
|
1222 |
set asm-arch powerpc
|
|
1223 |
}
|
|
1224 |
+ "sh*-linux*" {
|
|
1225 |
+ set asm-arch sh-linux
|
|
1226 |
+ set asm-flags "-I${srcdir}/${subdir} -I${objdir}/${subdir}"
|
|
1227 |
+ set debug-flags "-gdwarf-2"
|
|
1228 |
+ }
|
|
1229 |
"sh*-*-*" {
|
|
1230 |
set asm-arch sh
|
|
1231 |
set debug-flags "-gdwarf-2"
|
|
1232 |
diff --git a/gdb/testsuite/gdb.asm/sh-linux.inc b/gdb/testsuite/gdb.asm/sh-linux.inc
|
|
1233 |
new file mode 100644
|
|
1234 |
index 0000000..4a0f669
|
|
1235 |
--- /dev/null
|
|
1236 |
+++ b/gdb/testsuite/gdb.asm/sh-linux.inc
|
|
1237 |
@@ -0,0 +1,78 @@
|
|
1238 |
+# You'll find a bunch of nop opcodes in the below macros. They are
|
|
1239 |
+# there to keep the code correctly aligned. Be careful to maintain
|
|
1240 |
+# them when changing the code.
|
|
1241 |
+
|
|
1242 |
+ comment "subroutine declare"
|
|
1243 |
+ .purgem gdbasm_declare
|
|
1244 |
+ .macro gdbasm_declare name
|
|
1245 |
+ .align 1
|
|
1246 |
+ .global \name
|
|
1247 |
+\name:
|
|
1248 |
+ .endm
|
|
1249 |
+
|
|
1250 |
+ comment "subroutine prologue"
|
|
1251 |
+ .macro gdbasm_enter
|
|
1252 |
+ mov.l r14,@-r15
|
|
1253 |
+ sts.l pr,@-r15
|
|
1254 |
+ mov r15,r14
|
|
1255 |
+ nop
|
|
1256 |
+ .endm
|
|
1257 |
+
|
|
1258 |
+ comment "subroutine epilogue"
|
|
1259 |
+ .macro gdbasm_leave
|
|
1260 |
+ mov r14,r15
|
|
1261 |
+ lds.l @r15+,pr
|
|
1262 |
+ mov.l @r15+,r14
|
|
1263 |
+ rts
|
|
1264 |
+ nop
|
|
1265 |
+ nop
|
|
1266 |
+ .endm
|
|
1267 |
+
|
|
1268 |
+ comment "subroutine end"
|
|
1269 |
+ .purgem gdbasm_end
|
|
1270 |
+ .macro gdbasm_end name
|
|
1271 |
+ .size \name, .-_foo1
|
|
1272 |
+ .align 1
|
|
1273 |
+ .endm
|
|
1274 |
+
|
|
1275 |
+ comment "subroutine call"
|
|
1276 |
+ .macro gdbasm_call subr
|
|
1277 |
+ mov.l .Lconst\@,r1
|
|
1278 |
+ bra .Lafterconst\@
|
|
1279 |
+ nop
|
|
1280 |
+ .align 2
|
|
1281 |
+.Lconst\@:
|
|
1282 |
+ .long \subr
|
|
1283 |
+.Lafterconst\@:
|
|
1284 |
+ jsr @r1
|
|
1285 |
+ nop
|
|
1286 |
+ .endm
|
|
1287 |
+
|
|
1288 |
+ .macro gdbasm_several_nops
|
|
1289 |
+ nop
|
|
1290 |
+ nop
|
|
1291 |
+ nop
|
|
1292 |
+ nop
|
|
1293 |
+ .endm
|
|
1294 |
+
|
|
1295 |
+ comment "exit (0)"
|
|
1296 |
+ .macro gdbasm_exit0
|
|
1297 |
+ sleep
|
|
1298 |
+ nop
|
|
1299 |
+ .endm
|
|
1300 |
+
|
|
1301 |
+ comment "crt0 startup"
|
|
1302 |
+ .macro gdbasm_startup
|
|
1303 |
+ mov #0,r14
|
|
1304 |
+ .endm
|
|
1305 |
+
|
|
1306 |
+ comment "Declare a data variable"
|
|
1307 |
+ .purgem gdbasm_datavar
|
|
1308 |
+ .macro gdbasm_datavar name value
|
|
1309 |
+ .data
|
|
1310 |
+ .align 2
|
|
1311 |
+ .type \name, @object
|
|
1312 |
+ .size \name, 4
|
|
1313 |
+\name:
|
|
1314 |
+ .long \value
|
|
1315 |
+ .endm
|
|
1316 |
diff --git a/gdb/testsuite/gdb.asm/sh.inc b/gdb/testsuite/gdb.asm/sh.inc
|
|
1317 |
index 9ea1b67..c1f189d 100644
|
|
1318 |
--- a/gdb/testsuite/gdb.asm/sh.inc
|
|
1319 |
+++ b/gdb/testsuite/gdb.asm/sh.inc
|
|
1320 |
@@ -40,9 +40,8 @@
|
|
1321 |
mov.l .Lconst\@,r1
|
|
1322 |
bra .Lafterconst\@
|
|
1323 |
nop
|
|
1324 |
- nop
|
|
1325 |
-.Lconst\@:
|
|
1326 |
.align 2
|
|
1327 |
+.Lconst\@:
|
|
1328 |
.long \subr
|
|
1329 |
.align 1
|
|
1330 |
.Lafterconst\@:
|
|
1331 |
diff --git a/gdb/testsuite/gdb.base/annota1.c b/gdb/testsuite/gdb.base/annota1.c
|
|
1332 |
index 6a13ee9..fb8aa53 100644
|
|
1333 |
--- a/gdb/testsuite/gdb.base/annota1.c
|
|
1334 |
+++ b/gdb/testsuite/gdb.base/annota1.c
|
|
1335 |
@@ -1,9 +1,9 @@
|
|
1336 |
#include <stdio.h>
|
|
1337 |
#include <signal.h>
|
|
1338 |
|
|
1339 |
-#ifdef __sh__
|
|
1340 |
-#define signal(a,b) /* Signals not supported on this target - make them go away */
|
|
1341 |
-#endif
|
|
1342 |
+
|
|
1343 |
+
|
|
1344 |
+
|
|
1345 |
|
|
1346 |
|
|
1347 |
#ifdef PROTOTYPES
|
|
1348 |
diff --git a/gdb/testsuite/gdb.base/annota3.c b/gdb/testsuite/gdb.base/annota3.c
|
|
1349 |
index 6a13ee9..fb8aa53 100644
|
|
1350 |
--- a/gdb/testsuite/gdb.base/annota3.c
|
|
1351 |
+++ b/gdb/testsuite/gdb.base/annota3.c
|
|
1352 |
@@ -1,9 +1,9 @@
|
|
1353 |
#include <stdio.h>
|
|
1354 |
#include <signal.h>
|
|
1355 |
|
|
1356 |
-#ifdef __sh__
|
|
1357 |
-#define signal(a,b) /* Signals not supported on this target - make them go away */
|
|
1358 |
-#endif
|
|
1359 |
+
|
|
1360 |
+
|
|
1361 |
+
|
|
1362 |
|
|
1363 |
|
|
1364 |
#ifdef PROTOTYPES
|
|
1365 |
diff --git a/gdb/testsuite/gdb.base/sigall.c b/gdb/testsuite/gdb.base/sigall.c
|
|
1366 |
index 28ae192..a8ff690 100644
|
|
1367 |
--- a/gdb/testsuite/gdb.base/sigall.c
|
|
1368 |
+++ b/gdb/testsuite/gdb.base/sigall.c
|
|
1369 |
@@ -1,9 +1,9 @@
|
|
1370 |
#include <signal.h>
|
|
1371 |
#include <unistd.h>
|
|
1372 |
|
|
1373 |
-#ifdef __sh__
|
|
1374 |
-#define signal(a,b) /* Signals not supported on this target - make them go away */
|
|
1375 |
-#endif
|
|
1376 |
+
|
|
1377 |
+
|
|
1378 |
+
|
|
1379 |
|
|
1380 |
/* Signal handlers, we set breakpoints in them to make sure that the
|
|
1381 |
signals really get delivered. */
|
|
1382 |
diff --git a/gdb/testsuite/gdb.base/signals.c b/gdb/testsuite/gdb.base/signals.c
|
|
1383 |
index f1ebcfc..cef4793 100644
|
|
1384 |
--- a/gdb/testsuite/gdb.base/signals.c
|
|
1385 |
+++ b/gdb/testsuite/gdb.base/signals.c
|
|
1386 |
@@ -3,10 +3,10 @@
|
|
1387 |
#include <signal.h>
|
|
1388 |
#include <unistd.h>
|
|
1389 |
|
|
1390 |
-#ifdef __sh__
|
|
1391 |
-#define signal(a,b) /* Signals not supported on this target - make them go away */
|
|
1392 |
-#define alarm(a) /* Ditto for alarm() */
|
|
1393 |
-#endif
|
|
1394 |
+
|
|
1395 |
+
|
|
1396 |
+
|
|
1397 |
+
|
|
1398 |
|
|
1399 |
static int count = 0;
|
|
1400 |
|
|
1401 |
--
|
|
1402 |
1.7.0.3
|
|
1403 |
|