/* Machine independent support for Solaris /proc (process file system) for GDB.
- Copyright (C) 1999-2020 Free Software Foundation, Inc.
+ Copyright (C) 1999-2021 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#include "nat/fork-inferior.h"
#include "gdbarch.h"
-#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
-
#include <sys/procfs.h>
#include <sys/fault.h>
#include <sys/syscall.h>
void detach (inferior *inf, int) override;
void resume (ptid_t, int, enum gdb_signal) override;
- ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+ ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
int find_memory_regions (find_memory_region_ftype func, void *data)
override;
- char *make_corefile_notes (bfd *, int *) override;
+ gdb::unique_xmalloc_ptr<char> make_corefile_notes (bfd *, int *) override;
bool info_proc (const char *, enum info_proc_what) override;
if (pid == getpid ())
error (_("Attaching GDB to itself is not a good idea..."));
+ /* Push the target if needed, ensure it gets un-pushed it if attach fails. */
+ target_unpush_up unpusher;
+ if (!target_is_pushed (this))
+ {
+ push_target (this);
+ unpusher.reset (this);
+ }
+
if (from_tty)
{
const char *exec_file = get_exec_file (0);
fflush (stdout);
}
+
do_attach (ptid_t (pid));
- if (!target_is_pushed (this))
- push_target (this);
+
+ /* Everything went fine, keep the target pushed. */
+ unpusher.release ();
}
void
ptid_t
procfs_target::wait (ptid_t ptid, struct target_waitstatus *status,
- int options)
+ target_wait_flags options)
{
/* First cut: loosely based on original version 2.1. */
procinfo *pi;
/*destroy_procinfo (pi);*/
}
+/* Dummy function to be sure fork_inferior uses fork(2) and not vfork(2).
+ This avoids a possible deadlock gdb and its vfork'ed child. */
+static void
+procfs_pre_trace (void)
+{
+}
+
/* This function is called BEFORE gdb forks the inferior process. Its
only real responsibility is to set things up for the fork, and tell
GDB which two functions to call after the fork (one for the parent,
push_target (this);
pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
- NULL, NULL, shell_file, NULL);
+ NULL, procfs_pre_trace, shell_file, NULL);
/* We have something that executes now. We'll be running through
the shell at this point (if startup-with-shell is true), but the
procfs_init_inferior (pid);
}
-/* An observer for the "inferior_created" event. */
-
-static void
-procfs_inferior_created (struct target_ops *ops, int from_tty)
-{
-}
-
/* Callback for update_thread_list. Calls "add_thread". */
static int
enum target_hw_bp_type type,
struct expression *cond)
{
- if (!target_have_steppable_watchpoint
+ if (!target_have_steppable_watchpoint ()
&& !gdbarch_have_nonsteppable_watchpoint (target_gdbarch ()))
/* When a hardware watchpoint fires off the PC will be left at
the instruction following the one which caused the
void
_initialize_procfs ()
{
- gdb::observers::inferior_created.attach (procfs_inferior_created);
-
add_com ("proc-trace-entry", no_class, proc_trace_sysentry_cmd,
_("Give a trace of entries into the syscall."));
add_com ("proc-trace-exit", no_class, proc_trace_sysexit_cmd,
/* =================== GCORE .NOTE "MODULE" =================== */
-static char *
+static void
procfs_do_thread_registers (bfd *obfd, ptid_t ptid,
- char *note_data, int *note_size,
- enum gdb_signal stop_signal)
+ gdb::unique_xmalloc_ptr<char> ¬e_data,
+ int *note_size, enum gdb_signal stop_signal)
{
struct regcache *regcache = get_thread_regcache (&the_procfs_target, ptid);
gdb_gregset_t gregs;
target_fetch_registers (regcache, -1);
fill_gregset (regcache, &gregs, -1);
- note_data = (char *) elfcore_write_lwpstatus (obfd,
- note_data,
- note_size,
- merged_pid,
- stop_signal,
- &gregs);
+ note_data.reset (elfcore_write_lwpstatus (obfd,
+ note_data.release (),
+ note_size,
+ merged_pid,
+ stop_signal,
+ &gregs));
fill_fpregset (regcache, &fpregs, -1);
- note_data = (char *) elfcore_write_prfpreg (obfd,
- note_data,
- note_size,
- &fpregs,
- sizeof (fpregs));
-
- return note_data;
+ note_data.reset (elfcore_write_prfpreg (obfd,
+ note_data.release (),
+ note_size,
+ &fpregs,
+ sizeof (fpregs)));
}
-struct procfs_corefile_thread_data {
+struct procfs_corefile_thread_data
+{
+ procfs_corefile_thread_data (bfd *obfd,
+ gdb::unique_xmalloc_ptr<char> ¬e_data,
+ int *note_size, gdb_signal stop_signal)
+ : obfd (obfd), note_data (note_data), note_size (note_size),
+ stop_signal (stop_signal)
+ {}
+
bfd *obfd;
- char *note_data;
+ gdb::unique_xmalloc_ptr<char> ¬e_data;
int *note_size;
enum gdb_signal stop_signal;
};
{
ptid_t ptid = ptid_t (pi->pid, thread->tid, 0);
- args->note_data = procfs_do_thread_registers (args->obfd, ptid,
- args->note_data,
- args->note_size,
- args->stop_signal);
+ procfs_do_thread_registers (args->obfd, ptid,
+ args->note_data,
+ args->note_size,
+ args->stop_signal);
}
return 0;
}
return GDB_SIGNAL_0;
}
-char *
+gdb::unique_xmalloc_ptr<char>
procfs_target::make_corefile_notes (bfd *obfd, int *note_size)
{
gdb_gregset_t gregs;
char fname[16] = {'\0'};
char psargs[80] = {'\0'};
procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
- char *note_data = NULL;
+ gdb::unique_xmalloc_ptr<char> note_data;
const char *inf_args;
- struct procfs_corefile_thread_data thread_args;
enum gdb_signal stop_signal;
if (get_exec_file (0))
}
}
- note_data = (char *) elfcore_write_prpsinfo (obfd,
- note_data,
- note_size,
- fname,
- psargs);
+ note_data.reset (elfcore_write_prpsinfo (obfd,
+ note_data.release (),
+ note_size,
+ fname,
+ psargs));
stop_signal = find_stop_signal ();
fill_gregset (get_current_regcache (), &gregs, -1);
- note_data = elfcore_write_pstatus (obfd, note_data, note_size,
- inferior_ptid.pid (),
- stop_signal, &gregs);
-
- thread_args.obfd = obfd;
- thread_args.note_data = note_data;
- thread_args.note_size = note_size;
- thread_args.stop_signal = stop_signal;
+ note_data.reset (elfcore_write_pstatus (obfd, note_data.release (), note_size,
+ inferior_ptid.pid (),
+ stop_signal, &gregs));
+
+ procfs_corefile_thread_data thread_args (obfd, note_data, note_size,
+ stop_signal);
proc_iterate_over_threads (pi, procfs_corefile_thread_callback,
&thread_args);
- note_data = thread_args.note_data;
gdb::optional<gdb::byte_vector> auxv =
target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL);
if (auxv && !auxv->empty ())
- note_data = elfcore_write_note (obfd, note_data, note_size,
- "CORE", NT_AUXV, auxv->data (),
- auxv->size ());
+ note_data.reset (elfcore_write_note (obfd, note_data.release (), note_size,
+ "CORE", NT_AUXV, auxv->data (),
+ auxv->size ()));
return note_data;
}