X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finf-child.c;h=eb7550a9c6544b08aeae33ee4547a5c945460080;hb=dbbca37d38772f0f75296b01b757225278eb51fc;hp=96330097e5231395123f2aafc883e5195e4f0cd7;hpb=ee057212343faef868b546ce17e9dfc3b370f8e0;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inf-child.c b/gdb/inf-child.c index 96330097e5..eb7550a9c6 100644 --- a/gdb/inf-child.c +++ b/gdb/inf-child.c @@ -1,14 +1,13 @@ /* Default child (native) target interface, for GDB when running under Unix. - Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1988-2014 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,9 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "regcache.h" @@ -27,33 +24,70 @@ #include "symtab.h" #include "target.h" #include "inferior.h" -#include "gdb_string.h" +#include +#include +#include "inf-child.h" +#include "gdb/fileio.h" +#include "agent.h" +#include "gdb_wait.h" +#include "filestuff.h" + +#include +#include +#include + +/* Helper function for child_wait and the derivatives of child_wait. + HOSTSTATUS is the waitstatus from wait() or the equivalent; store our + translation of that in OURSTATUS. */ +void +store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus) +{ + if (WIFEXITED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_EXITED; + ourstatus->value.integer = WEXITSTATUS (hoststatus); + } + else if (!WIFSTOPPED (hoststatus)) + { + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = gdb_signal_from_host (WTERMSIG (hoststatus)); + } + else + { + ourstatus->kind = TARGET_WAITKIND_STOPPED; + ourstatus->value.sig = gdb_signal_from_host (WSTOPSIG (hoststatus)); + } +} /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this for all registers. */ static void -inf_child_fetch_inferior_registers (int regnum) +inf_child_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { if (regnum == -1) { - for (regnum = 0; regnum < NUM_REGS; regnum++) - regcache_raw_supply (current_regcache, regnum, NULL); + for (regnum = 0; + regnum < gdbarch_num_regs (get_regcache_arch (regcache)); + regnum++) + regcache_raw_supply (regcache, regnum, NULL); } else - regcache_raw_supply (current_regcache, regnum, NULL); + regcache_raw_supply (regcache, regnum, NULL); } /* Store register REGNUM back into the inferior. If REGNUM is -1, do this for all registers (including the floating point registers). */ static void -inf_child_store_inferior_registers (int regnum) +inf_child_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) { } static void -inf_child_post_attach (int pid) +inf_child_post_attach (struct target_ops *self, int pid) { /* This version of Unix doesn't require a meaningful "post attach" operation by a debugger. */ @@ -66,7 +100,8 @@ inf_child_post_attach (int pid) program being debugged. */ static void -inf_child_prepare_to_store (void) +inf_child_prepare_to_store (struct target_ops *self, + struct regcache *regcache) { } @@ -77,111 +112,287 @@ inf_child_open (char *arg, int from_tty) } static void -inf_child_post_startup_inferior (ptid_t ptid) +inf_child_post_startup_inferior (struct target_ops *self, ptid_t ptid) { /* This version of Unix doesn't require a meaningful "post startup inferior" operation by a debugger. */ } -static void -inf_child_acknowledge_created_inferior (int pid) -{ - /* This version of Unix doesn't require a meaningful "acknowledge - created inferior" operation by a debugger. */ -} - -static void -inf_child_insert_fork_catchpoint (int pid) +static int +inf_child_follow_fork (struct target_ops *ops, int follow_child, + int detach_fork) { - /* This version of Unix doesn't support notification of fork + /* This version of Unix doesn't support following fork or vfork events. */ + return 0; } static int -inf_child_remove_fork_catchpoint (int pid) +inf_child_can_run (struct target_ops *self) { - /* This version of Unix doesn't support notification of fork - events. */ - return 0; + return 1; } -static void -inf_child_insert_vfork_catchpoint (int pid) +static char * +inf_child_pid_to_exec_file (struct target_ops *self, int pid) { - /* This version of Unix doesn't support notification of vfork - events. */ + /* This version of Unix doesn't support translation of a process ID + to the filename of the executable file. */ + return NULL; } + +/* Target file operations. */ + static int -inf_child_remove_vfork_catchpoint (int pid) +inf_child_fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p) { - /* This version of Unix doesn't support notification of vfork - events. */ + int open_flags = 0; + + if (fileio_open_flags & ~FILEIO_O_SUPPORTED) + return -1; + + if (fileio_open_flags & FILEIO_O_CREAT) + open_flags |= O_CREAT; + if (fileio_open_flags & FILEIO_O_EXCL) + open_flags |= O_EXCL; + if (fileio_open_flags & FILEIO_O_TRUNC) + open_flags |= O_TRUNC; + if (fileio_open_flags & FILEIO_O_APPEND) + open_flags |= O_APPEND; + if (fileio_open_flags & FILEIO_O_RDONLY) + open_flags |= O_RDONLY; + if (fileio_open_flags & FILEIO_O_WRONLY) + open_flags |= O_WRONLY; + if (fileio_open_flags & FILEIO_O_RDWR) + open_flags |= O_RDWR; +/* On systems supporting binary and text mode, always open files in + binary mode. */ +#ifdef O_BINARY + open_flags |= O_BINARY; +#endif + + *open_flags_p = open_flags; return 0; } static int -inf_child_follow_fork (struct target_ops *ops, int follow_child) +inf_child_errno_to_fileio_error (int errnum) { - /* This version of Unix doesn't support following fork or vfork - events. */ - return 0; + switch (errnum) + { + case EPERM: + return FILEIO_EPERM; + case ENOENT: + return FILEIO_ENOENT; + case EINTR: + return FILEIO_EINTR; + case EIO: + return FILEIO_EIO; + case EBADF: + return FILEIO_EBADF; + case EACCES: + return FILEIO_EACCES; + case EFAULT: + return FILEIO_EFAULT; + case EBUSY: + return FILEIO_EBUSY; + case EEXIST: + return FILEIO_EEXIST; + case ENODEV: + return FILEIO_ENODEV; + case ENOTDIR: + return FILEIO_ENOTDIR; + case EISDIR: + return FILEIO_EISDIR; + case EINVAL: + return FILEIO_EINVAL; + case ENFILE: + return FILEIO_ENFILE; + case EMFILE: + return FILEIO_EMFILE; + case EFBIG: + return FILEIO_EFBIG; + case ENOSPC: + return FILEIO_ENOSPC; + case ESPIPE: + return FILEIO_ESPIPE; + case EROFS: + return FILEIO_EROFS; + case ENOSYS: + return FILEIO_ENOSYS; + case ENAMETOOLONG: + return FILEIO_ENAMETOOLONG; + } + return FILEIO_EUNKNOWN; } -static void -inf_child_insert_exec_catchpoint (int pid) +/* Open FILENAME on the target, using FLAGS and MODE. Return a + target file descriptor, or -1 if an error occurs (and set + *TARGET_ERRNO). */ +static int +inf_child_fileio_open (struct target_ops *self, + const char *filename, int flags, int mode, + int *target_errno) { - /* This version of Unix doesn't support notification of exec - events. */ + int nat_flags; + int fd; + + if (inf_child_fileio_open_flags_to_host (flags, &nat_flags) == -1) + { + *target_errno = FILEIO_EINVAL; + return -1; + } + + /* We do not need to convert MODE, since the fileio protocol uses + the standard values. */ + fd = gdb_open_cloexec (filename, nat_flags, mode); + if (fd == -1) + *target_errno = inf_child_errno_to_fileio_error (errno); + + return fd; } +/* Write up to LEN bytes from WRITE_BUF to FD on the target. + Return the number of bytes written, or -1 if an error occurs + (and set *TARGET_ERRNO). */ static int -inf_child_remove_exec_catchpoint (int pid) +inf_child_fileio_pwrite (struct target_ops *self, + int fd, const gdb_byte *write_buf, int len, + ULONGEST offset, int *target_errno) { - /* This version of Unix doesn't support notification of exec - events. */ - return 0; + int ret; + +#ifdef HAVE_PWRITE + ret = pwrite (fd, write_buf, len, (long) offset); +#else + ret = -1; +#endif + /* If we have no pwrite or it failed for this file, use lseek/write. */ + if (ret == -1) + { + ret = lseek (fd, (long) offset, SEEK_SET); + if (ret != -1) + ret = write (fd, write_buf, len); + } + + if (ret == -1) + *target_errno = inf_child_errno_to_fileio_error (errno); + + return ret; } +/* Read up to LEN bytes FD on the target into READ_BUF. + Return the number of bytes read, or -1 if an error occurs + (and set *TARGET_ERRNO). */ static int -inf_child_reported_exec_events_per_exec_call (void) +inf_child_fileio_pread (struct target_ops *self, + int fd, gdb_byte *read_buf, int len, + ULONGEST offset, int *target_errno) { - /* This version of Unix doesn't support notification of exec - events. */ - return 1; + int ret; + +#ifdef HAVE_PREAD + ret = pread (fd, read_buf, len, (long) offset); +#else + ret = -1; +#endif + /* If we have no pread or it failed for this file, use lseek/read. */ + if (ret == -1) + { + ret = lseek (fd, (long) offset, SEEK_SET); + if (ret != -1) + ret = read (fd, read_buf, len); + } + + if (ret == -1) + *target_errno = inf_child_errno_to_fileio_error (errno); + + return ret; } +/* Close FD on the target. Return 0, or -1 if an error occurs + (and set *TARGET_ERRNO). */ static int -inf_child_can_run (void) +inf_child_fileio_close (struct target_ops *self, int fd, int *target_errno) { - return 1; -} + int ret; -static struct symtab_and_line * -inf_child_enable_exception_callback (enum exception_event_kind kind, - int enable) -{ - return (struct symtab_and_line *) NULL; + ret = close (fd); + if (ret == -1) + *target_errno = inf_child_errno_to_fileio_error (errno); + + return ret; } -static struct exception_event_record * -inf_child_get_current_exception_event (void) +/* Unlink FILENAME on the target. Return 0, or -1 if an error + occurs (and set *TARGET_ERRNO). */ +static int +inf_child_fileio_unlink (struct target_ops *self, + const char *filename, int *target_errno) { - return (struct exception_event_record *) NULL; + int ret; + + ret = unlink (filename); + if (ret == -1) + *target_errno = inf_child_errno_to_fileio_error (errno); + + return ret; } +/* Read value of symbolic link FILENAME on the target. Return a + null-terminated string allocated via xmalloc, or NULL if an error + occurs (and set *TARGET_ERRNO). */ static char * -inf_child_pid_to_exec_file (int pid) +inf_child_fileio_readlink (const char *filename, int *target_errno) { - /* This version of Unix doesn't support translation of a process ID - to the filename of the executable file. */ + /* We support readlink only on systems that also provide a compile-time + maximum path length (PATH_MAX), at least for now. */ +#if defined (HAVE_READLINK) && defined (PATH_MAX) + char buf[PATH_MAX]; + int len; + char *ret; + + len = readlink (filename, buf, sizeof buf); + if (len < 0) + { + *target_errno = inf_child_errno_to_fileio_error (errno); + return NULL; + } + + ret = xmalloc (len + 1); + memcpy (ret, buf, len); + ret[len] = '\0'; + return ret; +#else + *target_errno = FILEIO_ENOSYS; return NULL; +#endif +} + +static int +inf_child_use_agent (int use) +{ + if (agent_loaded_p ()) + { + use_agent = use; + return 1; + } + else + return 0; +} + +static int +inf_child_can_use_agent (void) +{ + return agent_loaded_p (); } struct target_ops * inf_child_target (void) { - struct target_ops *t = XZALLOC (struct target_ops); + struct target_ops *t = XCNEW (struct target_ops); + t->to_shortname = "child"; t->to_longname = "Unix child process"; t->to_doc = "Unix child process (started by the \"run\" command)."; @@ -199,26 +410,23 @@ inf_child_target (void) t->to_terminal_ours = terminal_ours; t->to_terminal_info = child_terminal_info; t->to_post_startup_inferior = inf_child_post_startup_inferior; - t->to_acknowledge_created_inferior = inf_child_acknowledge_created_inferior; - t->to_insert_fork_catchpoint = inf_child_insert_fork_catchpoint; - t->to_remove_fork_catchpoint = inf_child_remove_fork_catchpoint; - t->to_insert_vfork_catchpoint = inf_child_insert_vfork_catchpoint; - t->to_remove_vfork_catchpoint = inf_child_remove_vfork_catchpoint; t->to_follow_fork = inf_child_follow_fork; - t->to_insert_exec_catchpoint = inf_child_insert_exec_catchpoint; - t->to_remove_exec_catchpoint = inf_child_remove_exec_catchpoint; - t->to_reported_exec_events_per_exec_call = - inf_child_reported_exec_events_per_exec_call; t->to_can_run = inf_child_can_run; - t->to_enable_exception_callback = inf_child_enable_exception_callback; - t->to_get_current_exception_event = inf_child_get_current_exception_event; t->to_pid_to_exec_file = inf_child_pid_to_exec_file; t->to_stratum = process_stratum; - t->to_has_all_memory = 1; - t->to_has_memory = 1; - t->to_has_stack = 1; - t->to_has_registers = 1; - t->to_has_execution = 1; + t->to_has_all_memory = default_child_has_all_memory; + t->to_has_memory = default_child_has_memory; + t->to_has_stack = default_child_has_stack; + t->to_has_registers = default_child_has_registers; + t->to_has_execution = default_child_has_execution; + t->to_fileio_open = inf_child_fileio_open; + t->to_fileio_pwrite = inf_child_fileio_pwrite; + t->to_fileio_pread = inf_child_fileio_pread; + t->to_fileio_close = inf_child_fileio_close; + t->to_fileio_unlink = inf_child_fileio_unlink; + t->to_fileio_readlink = inf_child_fileio_readlink; t->to_magic = OPS_MAGIC; + t->to_use_agent = inf_child_use_agent; + t->to_can_use_agent = inf_child_can_use_agent; return t; }