1 /* SPU native-dependent code for GDB, the GNU debugger.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
6 This file is part of GDB.
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.
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.
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. */
25 #include "gdb_string.h"
28 #include "inf-ptrace.h"
33 #include <sys/ptrace.h>
34 #include <asm/ptrace.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
40 /* PPU side system calls. */
41 #define INSTR_SC 0x44000002
42 #define NR_spu_run 0x0116
45 /* Fetch PPU register REGNO. */
47 fetch_ppc_register (int regno
)
51 int tid
= TIDGET (inferior_ptid
);
53 tid
= PIDGET (inferior_ptid
);
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. */
64 ptrace (PPC_PTRACE_PEEKUSR_3264
, tid
,
65 (PTRACE_TYPE_ARG3
) (regno
* 8), buf
);
67 ptrace (PPC_PTRACE_PEEKUSR_3264
, tid
,
68 (PTRACE_TYPE_ARG3
) (regno
* 8 + 4), buf
+ 4);
70 return (CORE_ADDR
) *(unsigned long long *)buf
;
75 res
= ptrace (PT_READ_U
, tid
,
76 (PTRACE_TYPE_ARG3
) (regno
* sizeof (PTRACE_TYPE_RET
)), 0);
80 xsnprintf (mess
, sizeof mess
, "reading PPC register #%d", regno
);
81 perror_with_name (_(mess
));
84 return (CORE_ADDR
) (unsigned long) res
;
87 /* Fetch WORD from PPU memory at (aligned) MEMADDR in thread TID. */
89 fetch_ppc_memory_1 (int tid
, CORE_ADDR memaddr
, PTRACE_TYPE_RET
*word
)
96 unsigned long long addr_8
= (unsigned long long) memaddr
;
97 ptrace (PPC_PTRACE_PEEKTEXT_3264
, tid
, (PTRACE_TYPE_ARG3
) &addr_8
, word
);
101 *word
= ptrace (PT_READ_I
, tid
, (PTRACE_TYPE_ARG3
) (size_t) memaddr
, 0);
106 /* Store WORD into PPU memory at (aligned) MEMADDR in thread TID. */
108 store_ppc_memory_1 (int tid
, CORE_ADDR memaddr
, PTRACE_TYPE_RET word
)
112 #ifndef __powerpc64__
115 unsigned long long addr_8
= (unsigned long long) memaddr
;
116 ptrace (PPC_PTRACE_POKEDATA_3264
, tid
, (PTRACE_TYPE_ARG3
) &addr_8
, word
);
120 ptrace (PT_WRITE_D
, tid
, (PTRACE_TYPE_ARG3
) (size_t) memaddr
, word
);
125 /* Fetch LEN bytes of PPU memory at MEMADDR to MYADDR. */
127 fetch_ppc_memory (CORE_ADDR memaddr
, gdb_byte
*myaddr
, int len
)
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
;
136 int tid
= TIDGET (inferior_ptid
);
138 tid
= PIDGET (inferior_ptid
);
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)
146 (char *) buffer
+ (memaddr
& (sizeof (PTRACE_TYPE_RET
) - 1)),
152 /* Store LEN bytes from MYADDR to PPU memory at MEMADDR. */
154 store_ppc_memory (CORE_ADDR memaddr
, const gdb_byte
*myaddr
, int len
)
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
;
163 int tid
= TIDGET (inferior_ptid
);
165 tid
= PIDGET (inferior_ptid
);
167 buffer
= (PTRACE_TYPE_RET
*) alloca (count
* sizeof (PTRACE_TYPE_RET
));
169 if (addr
!= memaddr
|| len
< (int) sizeof (PTRACE_TYPE_RET
))
170 if ((ret
= fetch_ppc_memory_1 (tid
, addr
, &buffer
[0])) != 0)
174 if ((ret
= fetch_ppc_memory_1 (tid
, addr
+ (count
- 1)
175 * sizeof (PTRACE_TYPE_RET
),
176 &buffer
[count
- 1])) != 0)
179 memcpy ((char *) buffer
+ (memaddr
& (sizeof (PTRACE_TYPE_RET
) - 1)),
182 for (i
= 0; i
< count
; i
++, addr
+= sizeof (PTRACE_TYPE_RET
))
183 if ((ret
= store_ppc_memory_1 (tid
, addr
, buffer
[i
])) != 0)
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. */
194 parse_spufs_run (int *fd
, CORE_ADDR
*addr
)
197 CORE_ADDR pc
= fetch_ppc_register (32); /* nip */
199 /* Fetch instruction preceding current NIP. */
200 if (fetch_ppc_memory (pc
-4, buf
, 4) != 0)
202 /* It should be a "sc" instruction. */
203 if (extract_unsigned_integer (buf
, 4) != INSTR_SC
)
205 /* System call number should be NR_spu_run. */
206 if (fetch_ppc_register (0) != NR_spu_run
)
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);
216 /* Copy LEN bytes at OFFSET in spufs file ANNEX into/from READBUF or WRITEBUF,
217 using the /proc file system. */
219 spu_proc_xfer_spu (const char *annex
, gdb_byte
*readbuf
,
220 const gdb_byte
*writebuf
,
221 ULONGEST offset
, LONGEST len
)
226 int pid
= PIDGET (inferior_ptid
);
231 xsnprintf (buf
, sizeof buf
, "/proc/%d/fd/%s", pid
, annex
);
232 fd
= open (buf
, writebuf
? O_WRONLY
: O_RDONLY
);
237 && lseek (fd
, (off_t
) offset
, SEEK_SET
) != (off_t
) offset
)
244 ret
= write (fd
, writebuf
, (size_t) len
);
246 ret
= read (fd
, readbuf
, (size_t) len
);
253 /* Inferior memory should contain an SPE executable image at location ADDR.
254 Allocate a BFD representing that executable. Return NULL on error. */
257 spu_bfd_iovec_open (struct bfd
*nbfd
, void *open_closure
)
263 spu_bfd_iovec_close (struct bfd
*nbfd
, void *stream
)
270 spu_bfd_iovec_pread (struct bfd
*abfd
, void *stream
, void *buf
,
271 file_ptr nbytes
, file_ptr offset
)
273 CORE_ADDR addr
= *(CORE_ADDR
*)stream
;
275 if (fetch_ppc_memory (addr
+ offset
, buf
, nbytes
) != 0)
277 bfd_set_error (bfd_error_invalid_operation
);
285 spu_bfd_open (CORE_ADDR addr
)
289 CORE_ADDR
*open_closure
= xmalloc (sizeof (CORE_ADDR
));
290 *open_closure
= addr
;
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
);
298 if (!bfd_check_format (nbfd
, bfd_object
))
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. */
312 spu_symbol_file_add_from_memory (int inferior_fd
)
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
)
327 if (sscanf (id
, "0x%llx", &addr
) != 1)
330 /* Open BFD representing SPE executable and read its symbols. */
331 nbfd
= spu_bfd_open (addr
);
333 symbol_file_add_from_bfd (nbfd
, 0, NULL
, 1, 0);
337 /* Override the post_startup_inferior routine to continue running
338 the inferior until the first spu_run system call. */
340 spu_child_post_startup_inferior (ptid_t ptid
)
345 int tid
= TIDGET (ptid
);
349 while (!parse_spufs_run (&fd
, &addr
))
351 ptrace (PT_SYSCALL
, tid
, (PTRACE_TYPE_ARG3
) 0, 0);
352 waitpid (tid
, NULL
, __WALL
| __WNOTHREAD
);
356 /* Override the post_attach routine to try load the SPE executable
357 file image from its copy inside the target process. */
359 spu_child_post_attach (int pid
)
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
))
369 ptrace (PT_SYSCALL
, pid
, (PTRACE_TYPE_ARG3
) 0, 0);
370 waitpid (pid
, NULL
, __WALL
| __WNOTHREAD
);
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
);
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. */
382 spu_child_wait (ptid_t ptid
, struct target_waitstatus
*ourstatus
)
390 set_sigint_trap (); /* Causes SIGINT to be passed on to the
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
);
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
))
410 clear_sigint_trap ();
412 while (pid
== -1 && save_errno
== EINTR
);
416 warning ("Child process unexpectedly missing: %s",
417 safe_strerror (save_errno
));
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
;
425 store_waitstatus (ourstatus
, status
);
426 return pid_to_ptid (pid
);
429 /* Override the fetch_inferior_register routine. */
431 spu_fetch_inferior_registers (int regno
)
436 /* We must be stopped on a spu_run system call. */
437 if (!parse_spufs_run (&fd
, &addr
))
440 /* The ID register holds the spufs file handle. */
441 if (regno
== -1 || regno
== SPU_ID_REGNUM
)
444 store_unsigned_integer (buf
, 4, fd
);
445 regcache_raw_supply (current_regcache
, SPU_ID_REGNUM
, buf
);
448 /* The NPC register is found at ADDR. */
449 if (regno
== -1 || regno
== SPU_PC_REGNUM
)
452 if (fetch_ppc_memory (addr
, buf
, 4) == 0)
453 regcache_raw_supply (current_regcache
, SPU_PC_REGNUM
, buf
);
456 /* The GPRs are found in the "regs" spufs file. */
457 if (regno
== -1 || (regno
>= 0 && regno
< SPU_NUM_GPRS
))
459 gdb_byte buf
[16 * SPU_NUM_GPRS
];
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);
470 /* Override the store_inferior_register routine. */
472 spu_store_inferior_registers (int regno
)
477 /* We must be stopped on a spu_run system call. */
478 if (!parse_spufs_run (&fd
, &addr
))
481 /* The NPC register is found at ADDR. */
482 if (regno
== -1 || regno
== SPU_PC_REGNUM
)
485 regcache_raw_collect (current_regcache
, SPU_PC_REGNUM
, buf
);
486 store_ppc_memory (addr
, buf
, 4);
489 /* The GPRs are found in the "regs" spufs file. */
490 if (regno
== -1 || (regno
>= 0 && regno
< SPU_NUM_GPRS
))
492 gdb_byte buf
[16 * SPU_NUM_GPRS
];
496 for (i
= 0; i
< SPU_NUM_GPRS
; i
++)
497 regcache_raw_collect (current_regcache
, i
, buf
+ i
*16);
499 xsnprintf (annex
, sizeof annex
, "%d/regs", fd
);
500 spu_proc_xfer_spu (annex
, NULL
, buf
, 0, sizeof buf
);
504 /* Override the to_xfer_partial routine. */
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
)
511 if (object
== TARGET_OBJECT_MEMORY
)
517 /* We must be stopped on a spu_run system call. */
518 if (!parse_spufs_run (&fd
, &addr
))
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
);
529 /* Override the to_can_use_hw_breakpoint routine. */
531 spu_can_use_hw_breakpoint (int type
, int cnt
, int othertype
)
537 /* Initialize SPU native target. */
539 _initialize_spu_nat (void)
541 /* Generic ptrace methods. */
542 struct target_ops
*t
;
543 t
= inf_ptrace_target ();
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
;
554 /* Register SPU target. */