]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/spu-multiarch.c
[binutils, ARM, 4/16] BF insns infrastructure with array of relocs in struct arm_it
[thirdparty/binutils-gdb.git] / gdb / spu-multiarch.c
CommitLineData
85e747d2 1/* Cell SPU GNU/Linux multi-architecture debugging support.
42a4f53d 2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
85e747d2
UW
3
4 Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
dcf7800b 10 the Free Software Foundation; either version 3 of the License, or
85e747d2
UW
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
dcf7800b 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
85e747d2
UW
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "gdbcmd.h"
85e747d2 24#include "arch-utils.h"
76727919 25#include "observable.h"
85e747d2
UW
26#include "inferior.h"
27#include "regcache.h"
28#include "symfile.h"
29#include "objfiles.h"
30#include "solib.h"
31#include "solist.h"
32
33#include "ppc-tdep.h"
34#include "ppc-linux-tdep.h"
35#include "spu-tdep.h"
36
f6ac5f3d
PA
37/* The SPU multi-architecture support target. */
38
d9f719f1
PA
39static const target_info spu_multiarch_target_info = {
40 "spu",
41 N_("SPU multi-architecture support."),
42 N_("SPU multi-architecture support.")
43};
44
f6ac5f3d
PA
45struct spu_multiarch_target final : public target_ops
46{
d9f719f1
PA
47 const target_info &info () const override
48 { return spu_multiarch_target_info; }
f6ac5f3d 49
66b4deae
PA
50 strata stratum () const override { return arch_stratum; }
51
f6ac5f3d
PA
52 void mourn_inferior () override;
53
57810aa7 54 void fetch_registers (struct regcache *, int) override;
f6ac5f3d
PA
55 void store_registers (struct regcache *, int) override;
56
57 enum target_xfer_status xfer_partial (enum target_object object,
58 const char *annex,
59 gdb_byte *readbuf,
60 const gdb_byte *writebuf,
61 ULONGEST offset, ULONGEST len,
62 ULONGEST *xfered_len) override;
63
64 int search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
65 const gdb_byte *pattern, ULONGEST pattern_len,
66 CORE_ADDR *found_addrp) override;
67
68 int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
69
70 struct gdbarch *thread_architecture (ptid_t) override;
71};
72
73static spu_multiarch_target spu_ops;
85e747d2
UW
74
75/* Number of SPE objects loaded into the current inferior. */
76static int spu_nr_solib;
77
78/* Stand-alone SPE executable? */
79#define spu_standalone_p() \
80 (symfile_objfile && symfile_objfile->obfd \
81 && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu)
82
83/* PPU side system calls. */
84#define INSTR_SC 0x44000002
85#define NR_spu_run 0x0116
86
87/* If the PPU thread is currently stopped on a spu_run system call,
88 return to FD and ADDR the file handle and NPC parameter address
89 used with the system call. Return non-zero if successful. */
90static int
91parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr)
92{
f5656ead 93 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
85e747d2
UW
94 struct gdbarch_tdep *tdep;
95 struct regcache *regcache;
e362b510 96 gdb_byte buf[4];
85e747d2
UW
97 ULONGEST regval;
98
99 /* If we're not on PPU, there's nothing to detect. */
f5656ead 100 if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_powerpc)
85e747d2
UW
101 return 0;
102
791bb1f4
UW
103 /* If we're called too early (e.g. after fork), we cannot
104 access the inferior yet. */
105 if (find_inferior_ptid (ptid) == NULL)
106 return 0;
107
85e747d2 108 /* Get PPU-side registers. */
f5656ead
TT
109 regcache = get_thread_arch_regcache (ptid, target_gdbarch ());
110 tdep = gdbarch_tdep (target_gdbarch ());
85e747d2
UW
111
112 /* Fetch instruction preceding current NIP. */
2989a365
TT
113 {
114 scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
115 inferior_ptid = ptid;
116 regval = target_read_memory (regcache_read_pc (regcache) - 4, buf, 4);
117 }
791bb1f4 118 if (regval != 0)
85e747d2
UW
119 return 0;
120 /* It should be a "sc" instruction. */
121 if (extract_unsigned_integer (buf, 4, byte_order) != INSTR_SC)
122 return 0;
123 /* System call number should be NR_spu_run. */
124 regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum, &regval);
125 if (regval != NR_spu_run)
126 return 0;
127
128 /* Register 3 contains fd, register 4 the NPC param pointer. */
129 regcache_cooked_read_unsigned (regcache, PPC_ORIG_R3_REGNUM, &regval);
130 *fd = (int) regval;
131 regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 4, &regval);
132 *addr = (CORE_ADDR) regval;
133 return 1;
134}
135
136/* Find gdbarch for SPU context SPUFS_FD. */
137static struct gdbarch *
138spu_gdbarch (int spufs_fd)
139{
140 struct gdbarch_info info;
141 gdbarch_info_init (&info);
142 info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
143 info.byte_order = BFD_ENDIAN_BIG;
144 info.osabi = GDB_OSABI_LINUX;
0dba2a6c 145 info.id = &spufs_fd;
85e747d2
UW
146 return gdbarch_find_by_info (info);
147}
148
149/* Override the to_thread_architecture routine. */
f6ac5f3d
PA
150struct gdbarch *
151spu_multiarch_target::thread_architecture (ptid_t ptid)
85e747d2
UW
152{
153 int spufs_fd;
154 CORE_ADDR spufs_addr;
155
156 if (parse_spufs_run (ptid, &spufs_fd, &spufs_addr))
157 return spu_gdbarch (spufs_fd);
158
d6ca69cd 159 return beneath ()->thread_architecture (ptid);
85e747d2
UW
160}
161
162/* Override the to_region_ok_for_hw_watchpoint routine. */
57810aa7 163
f6ac5f3d
PA
164int
165spu_multiarch_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
85e747d2 166{
85e747d2
UW
167 /* We cannot watch SPU local store. */
168 if (SPUADDR_SPU (addr) != -1)
169 return 0;
170
d6ca69cd 171 return beneath ()->region_ok_for_hw_watchpoint (addr, len);
85e747d2
UW
172}
173
174/* Override the to_fetch_registers routine. */
f6ac5f3d
PA
175
176void
177spu_multiarch_target::fetch_registers (struct regcache *regcache, int regno)
85e747d2 178{
ac7936df 179 struct gdbarch *gdbarch = regcache->arch ();
85e747d2 180 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
85e747d2
UW
181 int spufs_fd;
182 CORE_ADDR spufs_addr;
183
639a9038
SM
184 /* Since we use functions that rely on inferior_ptid, we need to set and
185 restore it. */
186 scoped_restore save_ptid
222312d3 187 = make_scoped_restore (&inferior_ptid, regcache->ptid ());
639a9038 188
85e747d2
UW
189 /* This version applies only if we're currently in spu_run. */
190 if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
191 {
d6ca69cd 192 beneath ()->fetch_registers (regcache, regno);
85e747d2
UW
193 return;
194 }
195
196 /* We must be stopped on a spu_run system call. */
197 if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
198 return;
199
200 /* The ID register holds the spufs file handle. */
201 if (regno == -1 || regno == SPU_ID_REGNUM)
202 {
e362b510 203 gdb_byte buf[4];
85e747d2 204 store_unsigned_integer (buf, 4, byte_order, spufs_fd);
73e1c03f 205 regcache->raw_supply (SPU_ID_REGNUM, buf);
85e747d2
UW
206 }
207
208 /* The NPC register is found in PPC memory at SPUFS_ADDR. */
209 if (regno == -1 || regno == SPU_PC_REGNUM)
210 {
e362b510 211 gdb_byte buf[4];
85e747d2 212
d6ca69cd 213 if (target_read (beneath (), TARGET_OBJECT_MEMORY, NULL,
85e747d2 214 buf, spufs_addr, sizeof buf) == sizeof buf)
73e1c03f 215 regcache->raw_supply (SPU_PC_REGNUM, buf);
85e747d2
UW
216 }
217
218 /* The GPRs are found in the "regs" spufs file. */
219 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
220 {
e362b510
PA
221 gdb_byte buf[16 * SPU_NUM_GPRS];
222 char annex[32];
85e747d2
UW
223 int i;
224
225 xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
d6ca69cd 226 if (target_read (beneath (), TARGET_OBJECT_SPU, annex,
85e747d2
UW
227 buf, 0, sizeof buf) == sizeof buf)
228 for (i = 0; i < SPU_NUM_GPRS; i++)
73e1c03f 229 regcache->raw_supply (i, buf + i*16);
85e747d2
UW
230 }
231}
232
233/* Override the to_store_registers routine. */
f6ac5f3d
PA
234
235void
236spu_multiarch_target::store_registers (struct regcache *regcache, int regno)
85e747d2 237{
ac7936df 238 struct gdbarch *gdbarch = regcache->arch ();
85e747d2
UW
239 int spufs_fd;
240 CORE_ADDR spufs_addr;
241
639a9038
SM
242 /* Since we use functions that rely on inferior_ptid, we need to set and
243 restore it. */
244 scoped_restore save_ptid
222312d3 245 = make_scoped_restore (&inferior_ptid, regcache->ptid ());
639a9038 246
85e747d2
UW
247 /* This version applies only if we're currently in spu_run. */
248 if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
249 {
d6ca69cd 250 beneath ()->store_registers (regcache, regno);
85e747d2
UW
251 return;
252 }
253
254 /* We must be stopped on a spu_run system call. */
255 if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
256 return;
257
258 /* The NPC register is found in PPC memory at SPUFS_ADDR. */
259 if (regno == -1 || regno == SPU_PC_REGNUM)
260 {
e362b510 261 gdb_byte buf[4];
34a79281 262 regcache->raw_collect (SPU_PC_REGNUM, buf);
85e747d2 263
d6ca69cd 264 target_write (beneath (), TARGET_OBJECT_MEMORY, NULL,
85e747d2
UW
265 buf, spufs_addr, sizeof buf);
266 }
267
268 /* The GPRs are found in the "regs" spufs file. */
269 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
270 {
e362b510
PA
271 gdb_byte buf[16 * SPU_NUM_GPRS];
272 char annex[32];
85e747d2
UW
273 int i;
274
275 for (i = 0; i < SPU_NUM_GPRS; i++)
34a79281 276 regcache->raw_collect (i, buf + i*16);
85e747d2
UW
277
278 xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
d6ca69cd 279 target_write (beneath (), TARGET_OBJECT_SPU, annex,
85e747d2
UW
280 buf, 0, sizeof buf);
281 }
282}
283
284/* Override the to_xfer_partial routine. */
f6ac5f3d
PA
285
286enum target_xfer_status
287spu_multiarch_target::xfer_partial (enum target_object object,
288 const char *annex, gdb_byte *readbuf,
289 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
290 ULONGEST *xfered_len)
85e747d2 291{
d6ca69cd 292 struct target_ops *ops_beneath = this->beneath ();
85e747d2
UW
293
294 /* Use the "mem" spufs file to access SPU local store. */
295 if (object == TARGET_OBJECT_MEMORY)
296 {
297 int fd = SPUADDR_SPU (offset);
298 CORE_ADDR addr = SPUADDR_ADDR (offset);
d2ed6730
UW
299 char mem_annex[32], lslr_annex[32];
300 gdb_byte buf[32];
301 ULONGEST lslr;
9b409511 302 enum target_xfer_status ret;
85e747d2 303
d2ed6730 304 if (fd >= 0)
85e747d2
UW
305 {
306 xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
f6ac5f3d
PA
307 ret = ops_beneath->xfer_partial (TARGET_OBJECT_SPU,
308 mem_annex, readbuf, writebuf,
309 addr, len, xfered_len);
9b409511 310 if (ret == TARGET_XFER_OK)
d2ed6730
UW
311 return ret;
312
313 /* SPU local store access wraps the address around at the
314 local store limit. We emulate this here. To avoid needing
315 an extra access to retrieve the LSLR, we only do that after
316 trying the original address first, and getting end-of-file. */
317 xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd);
318 memset (buf, 0, sizeof buf);
f6ac5f3d
PA
319 if (ops_beneath->xfer_partial (TARGET_OBJECT_SPU,
320 lslr_annex, buf, NULL,
321 0, sizeof buf, xfered_len)
9b409511 322 != TARGET_XFER_OK)
d2ed6730
UW
323 return ret;
324
001f13d8 325 lslr = strtoulst ((char *) buf, NULL, 16);
f6ac5f3d
PA
326 return ops_beneath->xfer_partial (TARGET_OBJECT_SPU,
327 mem_annex, readbuf, writebuf,
328 addr & lslr, len, xfered_len);
85e747d2
UW
329 }
330 }
331
f6ac5f3d
PA
332 return ops_beneath->xfer_partial (object, annex,
333 readbuf, writebuf, offset, len, xfered_len);
85e747d2
UW
334}
335
336/* Override the to_search_memory routine. */
f6ac5f3d
PA
337int
338spu_multiarch_target::search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
339 const gdb_byte *pattern, ULONGEST pattern_len,
340 CORE_ADDR *found_addrp)
85e747d2 341{
e75fdfca
TT
342 /* For SPU local store, always fall back to the simple method. */
343 if (SPUADDR_SPU (start_addr) >= 0)
f6ac5f3d 344 return simple_search_memory (this, start_addr, search_space_len,
85e747d2
UW
345 pattern, pattern_len, found_addrp);
346
d6ca69cd
PA
347 return beneath ()->search_memory (start_addr, search_space_len,
348 pattern, pattern_len, found_addrp);
85e747d2
UW
349}
350
351
352/* Push and pop the SPU multi-architecture support target. */
353
354static void
355spu_multiarch_activate (void)
356{
357 /* If GDB was configured without SPU architecture support,
358 we cannot install SPU multi-architecture support either. */
359 if (spu_gdbarch (-1) == NULL)
360 return;
361
362 push_target (&spu_ops);
363
364 /* Make sure the thread architecture is re-evaluated. */
365 registers_changed ();
366}
367
368static void
369spu_multiarch_deactivate (void)
370{
371 unpush_target (&spu_ops);
372
373 /* Make sure the thread architecture is re-evaluated. */
374 registers_changed ();
375}
376
377static void
378spu_multiarch_inferior_created (struct target_ops *ops, int from_tty)
379{
380 if (spu_standalone_p ())
381 spu_multiarch_activate ();
382}
383
384static void
385spu_multiarch_solib_loaded (struct so_list *so)
386{
387 if (!spu_standalone_p ())
388 if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
389 if (spu_nr_solib++ == 0)
390 spu_multiarch_activate ();
391}
392
393static void
394spu_multiarch_solib_unloaded (struct so_list *so)
395{
396 if (!spu_standalone_p ())
397 if (so->abfd && bfd_get_arch (so->abfd) == bfd_arch_spu)
398 if (--spu_nr_solib == 0)
399 spu_multiarch_deactivate ();
400}
401
f6ac5f3d
PA
402void
403spu_multiarch_target::mourn_inferior ()
85e747d2 404{
d6ca69cd 405 beneath ()->mourn_inferior ();
85e747d2
UW
406 spu_multiarch_deactivate ();
407}
408
85e747d2
UW
409void
410_initialize_spu_multiarch (void)
411{
85e747d2 412 /* Install observers to watch for SPU objects. */
76727919
TT
413 gdb::observers::inferior_created.attach (spu_multiarch_inferior_created);
414 gdb::observers::solib_loaded.attach (spu_multiarch_solib_loaded);
415 gdb::observers::solib_unloaded.attach (spu_multiarch_solib_unloaded);
85e747d2
UW
416}
417