fd3673c6a234a6c9eb1a066eea33c49a2584f1ae
[binutils-gdb.git] / gdb / spu-linux-nat.c
1 /* SPU native-dependent code for GDB, the GNU debugger.
2 Copyright (C) 2006 Free Software Foundation, Inc.
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
10 the Free Software Foundation; either version 2 of the License, or
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23 #include "defs.h"
24 #include "gdbcore.h"
25 #include "gdb_string.h"
26 #include "target.h"
27 #include "inferior.h"
28 #include "inf-ptrace.h"
29 #include "regcache.h"
30 #include "symfile.h"
31 #include "gdb_wait.h"
32
33 #include <sys/ptrace.h>
34 #include <asm/ptrace.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37
38 #include "spu-tdep.h"
39
40 /* PPU side system calls. */
41 #define INSTR_SC 0x44000002
42 #define NR_spu_run 0x0116
43
44
45 /* Fetch PPU register REGNO. */
46 static CORE_ADDR
47 fetch_ppc_register (int regno)
48 {
49 PTRACE_TYPE_RET res;
50
51 int tid = TIDGET (inferior_ptid);
52 if (tid == 0)
53 tid = PIDGET (inferior_ptid);
54
55 #ifndef __powerpc64__
56 /* If running as a 32-bit process on a 64-bit system, we attempt
57 to get the full 64-bit register content of the target process.
58 If the PPC special ptrace call fails, we're on a 32-bit system;
59 just fall through to the regular ptrace call in that case. */
60 {
61 gdb_byte buf[8];
62
63 errno = 0;
64 ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
65 (PTRACE_TYPE_ARG3) (regno * 8), buf);
66 if (errno == 0)
67 ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
68 (PTRACE_TYPE_ARG3) (regno * 8 + 4), buf + 4);
69 if (errno == 0)
70 return (CORE_ADDR) *(unsigned long long *)buf;
71 }
72 #endif
73
74 errno = 0;
75 res = ptrace (PT_READ_U, tid,
76 (PTRACE_TYPE_ARG3) (regno * sizeof (PTRACE_TYPE_RET)), 0);
77 if (errno != 0)
78 {
79 char mess[128];
80 xsnprintf (mess, sizeof mess, "reading PPC register #%d", regno);
81 perror_with_name (_(mess));
82 }
83
84 return (CORE_ADDR) (unsigned long) res;
85 }
86
87 /* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID. */
88 static int
89 fetch_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET *word)
90 {
91 errno = 0;
92
93 #ifndef __powerpc64__
94 if (memaddr >> 32)
95 {
96 unsigned long long addr_8 = (unsigned long long) memaddr;
97 ptrace (PPC_PTRACE_PEEKTEXT_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
98 }
99 else
100 #endif
101 *word = ptrace (PT_READ_I, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, 0);
102
103 return errno;
104 }
105
106 /* Store WORD into PPU memory at (aligned) MEMADDR in thread TID. */
107 static int
108 store_ppc_memory_1 (int tid, CORE_ADDR memaddr, PTRACE_TYPE_RET word)
109 {
110 errno = 0;
111
112 #ifndef __powerpc64__
113 if (memaddr >> 32)
114 {
115 unsigned long long addr_8 = (unsigned long long) memaddr;
116 ptrace (PPC_PTRACE_POKEDATA_3264, tid, (PTRACE_TYPE_ARG3) &addr_8, word);
117 }
118 else
119 #endif
120 ptrace (PT_WRITE_D, tid, (PTRACE_TYPE_ARG3) (size_t) memaddr, word);
121
122 return errno;
123 }
124
125 /* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR. */
126 static int
127 fetch_ppc_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
128 {
129 int i, ret;
130
131 CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
132 int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
133 / sizeof (PTRACE_TYPE_RET));
134 PTRACE_TYPE_RET *buffer;
135
136 int tid = TIDGET (inferior_ptid);
137 if (tid == 0)
138 tid = PIDGET (inferior_ptid);
139
140 buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
141 for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
142 if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[i])) != 0)
143 return ret;
144
145 memcpy (myaddr,
146 (char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
147 len);
148
149 return 0;
150 }
151
152 /* Store LEN bytes from MYADDR to PPU memory at MEMADDR. */
153 static int
154 store_ppc_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
155 {
156 int i, ret;
157
158 CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_TYPE_RET);
159 int count = ((((memaddr + len) - addr) + sizeof (PTRACE_TYPE_RET) - 1)
160 / sizeof (PTRACE_TYPE_RET));
161 PTRACE_TYPE_RET *buffer;
162
163 int tid = TIDGET (inferior_ptid);
164 if (tid == 0)
165 tid = PIDGET (inferior_ptid);
166
167 buffer = (PTRACE_TYPE_RET *) alloca (count * sizeof (PTRACE_TYPE_RET));
168
169 if (addr != memaddr || len < (int) sizeof (PTRACE_TYPE_RET))
170 if ((ret = fetch_ppc_memory_1 (tid, addr, &buffer[0])) != 0)
171 return ret;
172
173 if (count > 1)
174 if ((ret = fetch_ppc_memory_1 (tid, addr + (count - 1)
175 * sizeof (PTRACE_TYPE_RET),
176 &buffer[count - 1])) != 0)
177 return ret;
178
179 memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_TYPE_RET) - 1)),
180 myaddr, len);
181
182 for (i = 0; i < count; i++, addr += sizeof (PTRACE_TYPE_RET))
183 if ((ret = store_ppc_memory_1 (tid, addr, buffer[i])) != 0)
184 return ret;
185
186 return 0;
187 }
188
189
190 /* If the PPU thread is currently stopped on a spu_run system call,
191 return to FD and ADDR the file handle and NPC parameter address
192 used with the system call. Return non-zero if successful. */
193 static int
194 parse_spufs_run (int *fd, CORE_ADDR *addr)
195 {
196 gdb_byte buf[4];
197 CORE_ADDR pc = fetch_ppc_register (32); /* nip */
198
199 /* Fetch instruction preceding current NIP. */
200 if (fetch_ppc_memory (pc-4, buf, 4) != 0)
201 return 0;
202 /* It should be a "sc" instruction. */
203 if (extract_unsigned_integer (buf, 4) != INSTR_SC)
204 return 0;
205 /* System call number should be NR_spu_run. */
206 if (fetch_ppc_register (0) != NR_spu_run)
207 return 0;
208
209 /* Register 3 contains fd, register 4 the NPC param pointer. */
210 *fd = fetch_ppc_register (34); /* orig_gpr3 */
211 *addr = fetch_ppc_register (4);
212 return 1;
213 }
214
215
216 /* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
217 using the /proc file system. */
218 static LONGEST
219 spu_proc_xfer_spu (const char *annex, gdb_byte *readbuf,
220 const gdb_byte *writebuf,
221 ULONGEST offset, LONGEST len)
222 {
223 char buf[128];
224 int fd = 0;
225 int ret = -1;
226 int pid = PIDGET (inferior_ptid);
227
228 if (!annex)
229 return 0;
230
231 xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
232 fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
233 if (fd <= 0)
234 return -1;
235
236 if (offset != 0
237 && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
238 {
239 close (fd);
240 return -1;
241 }
242
243 if (writebuf)
244 ret = write (fd, writebuf, (size_t) len);
245 else if (readbuf)
246 ret = read (fd, readbuf, (size_t) len);
247
248 close (fd);
249 return ret;
250 }
251
252
253 /* Inferior memory should contain an SPE executable image at location ADDR.
254 Allocate a BFD representing that executable. Return NULL on error. */
255
256 static void *
257 spu_bfd_iovec_open (struct bfd *nbfd, void *open_closure)
258 {
259 return open_closure;
260 }
261
262 static int
263 spu_bfd_iovec_close (struct bfd *nbfd, void *stream)
264 {
265 xfree (stream);
266 return 1;
267 }
268
269 static file_ptr
270 spu_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf,
271 file_ptr nbytes, file_ptr offset)
272 {
273 CORE_ADDR addr = *(CORE_ADDR *)stream;
274
275 if (fetch_ppc_memory (addr + offset, buf, nbytes) != 0)
276 {
277 bfd_set_error (bfd_error_invalid_operation);
278 return -1;
279 }
280
281 return nbytes;
282 }
283
284 static bfd *
285 spu_bfd_open (CORE_ADDR addr)
286 {
287 struct bfd *nbfd;
288
289 CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR));
290 *open_closure = addr;
291
292 nbfd = bfd_openr_iovec (xstrdup ("<in-memory>"), "elf32-spu",
293 spu_bfd_iovec_open, open_closure,
294 spu_bfd_iovec_pread, spu_bfd_iovec_close);
295 if (!nbfd)
296 return NULL;
297
298 if (!bfd_check_format (nbfd, bfd_object))
299 {
300 bfd_close (nbfd);
301 return NULL;
302 }
303
304 return nbfd;
305 }
306
307 /* INFERIOR_FD is a file handle passed by the inferior to the
308 spu_run system call. Assuming the SPE context was allocated
309 by the libspe library, try to retrieve the main SPE executable
310 file from its copy within the target process. */
311 static void
312 spu_symbol_file_add_from_memory (int inferior_fd)
313 {
314 CORE_ADDR addr;
315 struct bfd *nbfd;
316
317 char id[128];
318 char annex[32];
319 int len;
320
321 /* Read object ID. */
322 xsnprintf (annex, sizeof annex, "%d/object-id", inferior_fd);
323 len = spu_proc_xfer_spu (annex, id, NULL, 0, sizeof id);
324 if (len <= 0 || len >= sizeof id)
325 return;
326 id[len] = 0;
327 if (sscanf (id, "0x%llx", &addr) != 1)
328 return;
329
330 /* Open BFD representing SPE executable and read its symbols. */
331 nbfd = spu_bfd_open (addr);
332 if (nbfd)
333 symbol_file_add_from_bfd (nbfd, 0, NULL, 1, 0);
334 }
335
336
337 /* Override the post_startup_inferior routine to continue running
338 the inferior until the first spu_run system call. */
339 static void
340 spu_child_post_startup_inferior (ptid_t ptid)
341 {
342 int fd;
343 CORE_ADDR addr;
344
345 int tid = TIDGET (ptid);
346 if (tid == 0)
347 tid = PIDGET (ptid);
348
349 while (!parse_spufs_run (&fd, &addr))
350 {
351 ptrace (PT_SYSCALL, tid, (PTRACE_TYPE_ARG3) 0, 0);
352 waitpid (tid, NULL, __WALL | __WNOTHREAD);
353 }
354 }
355
356 /* Override the post_attach routine to try load the SPE executable
357 file image from its copy inside the target process. */
358 static void
359 spu_child_post_attach (int pid)
360 {
361 int fd;
362 CORE_ADDR addr;
363
364 /* Like child_post_startup_inferior, if we happened to attach to
365 the inferior while it wasn't currently in spu_run, continue
366 running it until we get back there. */
367 while (!parse_spufs_run (&fd, &addr))
368 {
369 ptrace (PT_SYSCALL, pid, (PTRACE_TYPE_ARG3) 0, 0);
370 waitpid (pid, NULL, __WALL | __WNOTHREAD);
371 }
372
373 /* If the user has not provided an executable file, try to extract
374 the image from inside the target process. */
375 if (!get_exec_file (0))
376 spu_symbol_file_add_from_memory (fd);
377 }
378
379 /* Wait for child PTID to do something. Return id of the child,
380 minus_one_ptid in case of error; store status into *OURSTATUS. */
381 static ptid_t
382 spu_child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
383 {
384 int save_errno;
385 int status;
386 pid_t pid;
387
388 do
389 {
390 set_sigint_trap (); /* Causes SIGINT to be passed on to the
391 attached process. */
392 set_sigio_trap ();
393
394 pid = waitpid (PIDGET (ptid), &status, 0);
395 if (pid == -1 && errno == ECHILD)
396 /* Try again with __WCLONE to check cloned processes. */
397 pid = waitpid (PIDGET (ptid), &status, __WCLONE);
398
399 save_errno = errno;
400
401 /* Make sure we don't report an event for the exit of the
402 original program, if we've detached from it. */
403 if (pid != -1 && !WIFSTOPPED (status) && pid != PIDGET (inferior_ptid))
404 {
405 pid = -1;
406 save_errno = EINTR;
407 }
408
409 clear_sigio_trap ();
410 clear_sigint_trap ();
411 }
412 while (pid == -1 && save_errno == EINTR);
413
414 if (pid == -1)
415 {
416 warning ("Child process unexpectedly missing: %s",
417 safe_strerror (save_errno));
418
419 /* Claim it exited with unknown signal. */
420 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
421 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
422 return minus_one_ptid;
423 }
424
425 store_waitstatus (ourstatus, status);
426 return pid_to_ptid (pid);
427 }
428
429 /* Override the fetch_inferior_register routine. */
430 static void
431 spu_fetch_inferior_registers (int regno)
432 {
433 int fd;
434 CORE_ADDR addr;
435
436 /* We must be stopped on a spu_run system call. */
437 if (!parse_spufs_run (&fd, &addr))
438 return;
439
440 /* The ID register holds the spufs file handle. */
441 if (regno == -1 || regno == SPU_ID_REGNUM)
442 {
443 char buf[4];
444 store_unsigned_integer (buf, 4, fd);
445 regcache_raw_supply (current_regcache, SPU_ID_REGNUM, buf);
446 }
447
448 /* The NPC register is found at ADDR. */
449 if (regno == -1 || regno == SPU_PC_REGNUM)
450 {
451 gdb_byte buf[4];
452 if (fetch_ppc_memory (addr, buf, 4) == 0)
453 regcache_raw_supply (current_regcache, SPU_PC_REGNUM, buf);
454 }
455
456 /* The GPRs are found in the "regs" spufs file. */
457 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
458 {
459 gdb_byte buf[16 * SPU_NUM_GPRS];
460 char annex[32];
461 int i;
462
463 xsnprintf (annex, sizeof annex, "%d/regs", fd);
464 if (spu_proc_xfer_spu (annex, buf, NULL, 0, sizeof buf) == sizeof buf)
465 for (i = 0; i < SPU_NUM_GPRS; i++)
466 regcache_raw_supply (current_regcache, i, buf + i*16);
467 }
468 }
469
470 /* Override the store_inferior_register routine. */
471 static void
472 spu_store_inferior_registers (int regno)
473 {
474 int fd;
475 CORE_ADDR addr;
476
477 /* We must be stopped on a spu_run system call. */
478 if (!parse_spufs_run (&fd, &addr))
479 return;
480
481 /* The NPC register is found at ADDR. */
482 if (regno == -1 || regno == SPU_PC_REGNUM)
483 {
484 gdb_byte buf[4];
485 regcache_raw_collect (current_regcache, SPU_PC_REGNUM, buf);
486 store_ppc_memory (addr, buf, 4);
487 }
488
489 /* The GPRs are found in the "regs" spufs file. */
490 if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
491 {
492 gdb_byte buf[16 * SPU_NUM_GPRS];
493 char annex[32];
494 int i;
495
496 for (i = 0; i < SPU_NUM_GPRS; i++)
497 regcache_raw_collect (current_regcache, i, buf + i*16);
498
499 xsnprintf (annex, sizeof annex, "%d/regs", fd);
500 spu_proc_xfer_spu (annex, NULL, buf, 0, sizeof buf);
501 }
502 }
503
504 /* Override the to_xfer_partial routine. */
505 static LONGEST
506 spu_xfer_partial (struct target_ops *ops,
507 enum target_object object, const char *annex,
508 gdb_byte *readbuf, const gdb_byte *writebuf,
509 ULONGEST offset, LONGEST len)
510 {
511 if (object == TARGET_OBJECT_MEMORY)
512 {
513 int fd;
514 CORE_ADDR addr;
515 char mem_annex[32];
516
517 /* We must be stopped on a spu_run system call. */
518 if (!parse_spufs_run (&fd, &addr))
519 return 0;
520
521 /* Use the "mem" spufs file to access SPU local store. */
522 xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
523 return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len);
524 }
525
526 return 0;
527 }
528
529 /* Override the to_can_use_hw_breakpoint routine. */
530 static int
531 spu_can_use_hw_breakpoint (int type, int cnt, int othertype)
532 {
533 return 0;
534 }
535
536
537 /* Initialize SPU native target. */
538 void
539 _initialize_spu_nat (void)
540 {
541 /* Generic ptrace methods. */
542 struct target_ops *t;
543 t = inf_ptrace_target ();
544
545 /* Add SPU methods. */
546 t->to_post_attach = spu_child_post_attach;
547 t->to_post_startup_inferior = spu_child_post_startup_inferior;
548 t->to_wait = spu_child_wait;
549 t->to_fetch_registers = spu_fetch_inferior_registers;
550 t->to_store_registers = spu_store_inferior_registers;
551 t->to_xfer_partial = spu_xfer_partial;
552 t->to_can_use_hw_breakpoint = spu_can_use_hw_breakpoint;
553
554 /* Register SPU target. */
555 add_target (t);
556 }
557