41bf6acad7
This replaces XZALLOC with XCNEW and removes XZALLOC. This change is purely mechanical. 2014-01-13 Tom Tromey <tromey@redhat.com> * defs.h (XZALLOC): Remove. * ada-lang.c (get_ada_inferior_data): Use XCNEW, not XZALLOC. * ada-tasks.c (get_ada_tasks_pspace_data): Likewise. (get_ada_tasks_inferior_data): Likewise. * auto-load.c (get_auto_load_pspace_data): Likewise. * auxv.c (get_auxv_inferior_data): Likewise. * bfd-target.c (target_bfd_reopen): Likewise. * breakpoint.c (get_catch_syscall_inferior_data): Likewise. (deprecated_insert_raw_breakpoint): Likewise. * bsd-uthread.c (bsd_uthread_pid_to_str): Likewise. * corelow.c (core_open): Likewise. * darwin-nat.c (darwin_check_new_threads): Likewise. (darwin_attach_pid): Likewise. * dummy-frame.c (dummy_frame_push): Likewise. * dwarf2-frame.c (dwarf2_frame_cache): Likewise. * dwarf2loc.c (allocate_piece_closure): Likewise. * elfread.c (elf_symfile_segments): Likewise. * eval.c (ptrmath_type_p): Likewise. * exceptions.c (EXCEPTIONS_SIGJMP_BUF): Likewise. * gdbtypes.c (alloc_type_arch): Likewise. (alloc_type_instance): Likewise. * hppa-tdep.c (hppa_gdbarch_init): Likewise. * inf-child.c (inf_child_can_use_agent): Likewise. * inflow.c (get_inflow_inferior_data): Likewise. * infrun.c (save_infcall_suspend_state): Likewise. * jit.c (jit_reader_load): Likewise. (get_jit_objfile_data): Likewise. (get_jit_program_space_data): Likewise. (jit_object_open_impl): Likewise. (jit_symtab_open_impl): Likewise. (jit_block_open_impl): Likewise. (jit_frame_sniffer): Likewise. * linux-fork.c (add_fork): Likewise. * maint.c (make_command_stats_cleanup): Likewise. * objfiles.c (get_objfile_pspace_data): Likewise. * opencl-lang.c (struct lval_closure): Likewise. * osdata.c (osdata_start_osdata): Likewise. * progspace.c (new_address_space): Likewise. (add_program_space): Likewise. * remote-sim.c (get_sim_inferior_data): Likewise. * sh-tdep.c (sh_gdbarch_init): Likewise. * skip.c (Ignore): Likewise. (skip_delete_command): Likewise. * solib-aix.c (get_solib_aix_inferior_data): Likewise. (library_list_start_library): Likewise. (solib_aix_current_sos): Likewise. * solib-darwin.c (get_darwin_info): Likewise. (darwin_current_sos): Likewise. * solib-dsbt.c (get_dsbt_info): Likewise. * solib-ia64-hpux.c (new_so_list): Likewise. (ia64_hpux_get_solib_linkage_addr): Likewise. * solib-spu.c (append_ocl_sos): Likewise. (spu_current_sos): Likewise. * solib-svr4.c (get_svr4_info): Likewise. (svr4_keep_data_in_core): Likewise. (library_list_start_library): Likewise. (svr4_default_sos): Likewise. (svr4_read_so_list): Likewise. * solib-target.c (library_list_start_library): Likewise. (solib_target_current_sos): Likewise. * sparc-tdep.c (sparc32_gdbarch_init): Likewise. * symfile-debug.c (install_symfile_debug_logging): Likewise. * symfile.c (default_symfile_segments): Likewise. * target-descriptions.c (tdesc_data_init): Likewise. (tdesc_create_reg): Likewise. (struct tdesc_type *): Likewise. (tdesc_create_vector): Likewise. (tdesc_set_struct_size): Likewise. (struct tdesc_type *): Likewise. (tdesc_free_feature): Likewise. (tdesc_create_feature): Likewise. * windows-nat.c (windows_add_thread): Likewise. (windows_make_so): Likewise. * xml-support.c (gdb_xml_body_text): Likewise. (gdb_xml_create_parser_and_cleanup): Likewise. (xml_process_xincludes): Likewise. * xml-syscall.c (allocate_syscalls_info): Likewise. (syscall_create_syscall_desc): Likewise.
428 lines
11 KiB
C
428 lines
11 KiB
C
/* Default child (native) target interface, for GDB when running under
|
|
Unix.
|
|
|
|
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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
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, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "regcache.h"
|
|
#include "memattr.h"
|
|
#include "symtab.h"
|
|
#include "target.h"
|
|
#include "inferior.h"
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include "inf-child.h"
|
|
#include "gdb/fileio.h"
|
|
#include "agent.h"
|
|
#include "gdb_wait.h"
|
|
#include "filestuff.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
/* 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 (struct target_ops *ops,
|
|
struct regcache *regcache, int regnum)
|
|
{
|
|
if (regnum == -1)
|
|
{
|
|
for (regnum = 0;
|
|
regnum < gdbarch_num_regs (get_regcache_arch (regcache));
|
|
regnum++)
|
|
regcache_raw_supply (regcache, regnum, NULL);
|
|
}
|
|
else
|
|
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 (struct target_ops *ops,
|
|
struct regcache *regcache, int regnum)
|
|
{
|
|
}
|
|
|
|
static void
|
|
inf_child_post_attach (int pid)
|
|
{
|
|
/* This version of Unix doesn't require a meaningful "post attach"
|
|
operation by a debugger. */
|
|
}
|
|
|
|
/* Get ready to modify the registers array. On machines which store
|
|
individual registers, this doesn't need to do anything. On
|
|
machines which store all the registers in one fell swoop, this
|
|
makes sure that registers contains all the registers from the
|
|
program being debugged. */
|
|
|
|
static void
|
|
inf_child_prepare_to_store (struct regcache *regcache)
|
|
{
|
|
}
|
|
|
|
static void
|
|
inf_child_open (char *arg, int from_tty)
|
|
{
|
|
error (_("Use the \"run\" command to start a Unix child process."));
|
|
}
|
|
|
|
static void
|
|
inf_child_post_startup_inferior (ptid_t ptid)
|
|
{
|
|
/* This version of Unix doesn't require a meaningful "post startup
|
|
inferior" operation by a debugger. */
|
|
}
|
|
|
|
static int
|
|
inf_child_follow_fork (struct target_ops *ops, int follow_child,
|
|
int detach_fork)
|
|
{
|
|
/* This version of Unix doesn't support following fork or vfork
|
|
events. */
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
inf_child_can_run (void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static char *
|
|
inf_child_pid_to_exec_file (int pid)
|
|
{
|
|
/* 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_fileio_open_flags_to_host (int fileio_open_flags, int *open_flags_p)
|
|
{
|
|
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_errno_to_fileio_error (int errnum)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/* 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 (const char *filename, int flags, int mode,
|
|
int *target_errno)
|
|
{
|
|
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_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
|
|
ULONGEST offset, int *target_errno)
|
|
{
|
|
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_fileio_pread (int fd, gdb_byte *read_buf, int len,
|
|
ULONGEST offset, int *target_errno)
|
|
{
|
|
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_fileio_close (int fd, int *target_errno)
|
|
{
|
|
int ret;
|
|
|
|
ret = close (fd);
|
|
if (ret == -1)
|
|
*target_errno = inf_child_errno_to_fileio_error (errno);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Unlink FILENAME on the target. Return 0, or -1 if an error
|
|
occurs (and set *TARGET_ERRNO). */
|
|
static int
|
|
inf_child_fileio_unlink (const char *filename, int *target_errno)
|
|
{
|
|
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_fileio_readlink (const char *filename, int *target_errno)
|
|
{
|
|
/* 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 = 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).";
|
|
t->to_open = inf_child_open;
|
|
t->to_post_attach = inf_child_post_attach;
|
|
t->to_fetch_registers = inf_child_fetch_inferior_registers;
|
|
t->to_store_registers = inf_child_store_inferior_registers;
|
|
t->to_prepare_to_store = inf_child_prepare_to_store;
|
|
t->to_insert_breakpoint = memory_insert_breakpoint;
|
|
t->to_remove_breakpoint = memory_remove_breakpoint;
|
|
t->to_terminal_init = terminal_init_inferior;
|
|
t->to_terminal_inferior = terminal_inferior;
|
|
t->to_terminal_ours_for_output = terminal_ours_for_output;
|
|
t->to_terminal_save_ours = terminal_save_ours;
|
|
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_follow_fork = inf_child_follow_fork;
|
|
t->to_can_run = inf_child_can_run;
|
|
t->to_pid_to_exec_file = inf_child_pid_to_exec_file;
|
|
t->to_stratum = process_stratum;
|
|
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;
|
|
}
|