/* Machine independent support for Solaris /proc (process file system) for GDB.
- Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ Copyright (C) 1999-2024 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#include "infrun.h"
#include "target.h"
#include "gdbcore.h"
-#include "elf-bfd.h" /* for elfcore_write_* */
+#include "elf-bfd.h"
#include "gdbcmd.h"
#include "gdbthread.h"
#include "regcache.h"
#include <signal.h>
#include <ctype.h>
#include "gdb_bfd.h"
-#include "inflow.h"
#include "auxv.h"
#include "procfs.h"
#include "observable.h"
#include "gdbsupport/scoped_fd.h"
#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/buildargv.h"
+#include "cli/cli-style.h"
/* This module provides the interface between GDB and the
/proc file system, which is used on many versions of Unix
interface. */
#include <sys/types.h>
-#include <dirent.h> /* opendir/readdir, for listing the LWP's */
+#include <dirent.h>
-#include <fcntl.h> /* for O_RDONLY */
-#include <unistd.h> /* for "X_OK" */
-#include <sys/stat.h> /* for struct stat */
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
/* Note: procfs-utils.h must be included after the above system header
files, because it redefines various system calls using macros.
std::string pid_to_str (ptid_t) override;
- char *pid_to_exec_file (int pid) override;
+ const char *pid_to_exec_file (int pid) override;
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
bool info_proc (const char *, enum info_proc_what) override;
#if PR_MODEL_NATIVE == PR_MODEL_LP64
- int auxv_parse (gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+ int auxv_parse (const gdb_byte **readptr,
+ const gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
override;
#endif
is presented in 64-bit format. We need to provide a custom parser
to handle that. */
int
-procfs_target::auxv_parse (gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+procfs_target::auxv_parse (const gdb_byte **readptr,
+ const gdb_byte *endptr, CORE_ADDR *typep,
+ CORE_ADDR *valp)
{
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- gdb_byte *ptr = *readptr;
+ bfd_endian byte_order = gdbarch_byte_order (current_inferior ()->arch ());
+ const gdb_byte *ptr = *readptr;
if (endptr == ptr)
return 0;
int threads_valid: 1;
} procinfo;
-static char errmsg[128]; /* shared error msg buffer */
-
/* Function prototypes for procinfo module: */
static procinfo *find_procinfo_or_die (int pid, int tid);
static void
dead_procinfo (procinfo *pi, const char *msg, int kill_p)
{
- char procfile[80];
-
- if (pi->pathname)
- print_sys_errmsg (pi->pathname, errno);
- else
- {
- xsnprintf (procfile, sizeof (procfile), "process %d", pi->pid);
- print_sys_errmsg (procfile, errno);
- }
+ warning_filename_and_errno (pi->pathname, errno);
if (kill_p == KILL)
kill (pi->pid, SIGKILL);
(procinfo *pi,
int (*func) (procinfo *, procinfo *, void *),
void *ptr);
+static void proc_resume (procinfo *pi, ptid_t scope_ptid,
+ int step, enum gdb_signal signo);
static void
proc_warn (procinfo *pi, const char *func, int line)
{
- xsnprintf (errmsg, sizeof (errmsg), "procfs: %s line %d, %s",
- func, line, pi->pathname);
- print_sys_errmsg (errmsg, errno);
+ int saved_errno = errno;
+ warning ("procfs: %s line %d, %ps: %s",
+ func, line, styled_string (file_name_style.style (),
+ pi->pathname),
+ safe_strerror (saved_errno));
}
static void
proc_error (procinfo *pi, const char *func, int line)
{
- xsnprintf (errmsg, sizeof (errmsg), "procfs: %s line %d, %s",
- func, line, pi->pathname);
- perror_with_name (errmsg);
+ int saved_errno = errno;
+ error ("procfs: %s line %d, %s: %s",
+ func, line, pi->pathname, safe_strerror (saved_errno));
}
/* Updates the status struct in the procinfo. There is a 'valid'
if (!proc_get_status (pi))
return 0;
- *addr = (CORE_ADDR) gdbarch_pointer_to_address (target_gdbarch (),
- builtin_type (target_gdbarch ())->builtin_data_ptr,
- (gdb_byte *) &pi->prstatus.pr_lwp.pr_info.si_addr);
+ gdbarch *arch = current_inferior ()->arch ();
+ *addr = gdbarch_pointer_to_address
+ (arch, builtin_type (arch)->builtin_data_ptr,
+ (gdb_byte *) &pi->prstatus.pr_lwp.pr_info.si_addr);
return 1;
}
get_last_target_status (&wait_target, &wait_ptid, &wait_status);
if (wait_target == &the_procfs_target
&& wait_ptid == inferior_ptid
- && wait_status.kind == TARGET_WAITKIND_STOPPED
- && wait_status.value.sig == gdb_signal_from_host (signo)
+ && wait_status.kind () == TARGET_WAITKIND_STOPPED
+ && wait_status.sig () == gdb_signal_from_host (signo)
&& proc_get_status (pi)
&& pi->prstatus.pr_lwp.pr_info.si_signo == signo
)
static void *
procfs_address_to_host_pointer (CORE_ADDR addr)
{
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ gdbarch *arch = current_inferior ()->arch ();
+ type *ptr_type = builtin_type (arch)->builtin_data_ptr;
void *ptr;
- gdb_assert (sizeof (ptr) == TYPE_LENGTH (ptr_type));
- gdbarch_address_to_pointer (target_gdbarch (), ptr_type,
- (gdb_byte *) &ptr, addr);
+ gdb_assert (sizeof (ptr) == ptr_type->length ());
+ gdbarch_address_to_pointer (arch, ptr_type, (gdb_byte *) &ptr, addr);
return ptr;
}
if (pid == getpid ())
error (_("Attaching GDB to itself is not a good idea..."));
- if (from_tty)
+ /* Push the target if needed, ensure it gets un-pushed it if attach fails. */
+ inferior *inf = current_inferior ();
+ target_unpush_up unpusher;
+ if (!inf->target_is_pushed (this))
{
- const char *exec_file = get_exec_file (0);
+ inf->push_target (this);
+ unpusher.reset (this);
+ }
- if (exec_file)
- printf_filtered (_("Attaching to program `%s', %s\n"),
- exec_file, target_pid_to_str (ptid_t (pid)).c_str ());
- else
- printf_filtered (_("Attaching to %s\n"),
- target_pid_to_str (ptid_t (pid)).c_str ());
+ target_announce_attach (from_tty, pid);
- 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
procfs_target::detach (inferior *inf, int from_tty)
{
- int pid = inferior_ptid.pid ();
-
- if (from_tty)
- {
- const char *exec_file;
-
- exec_file = get_exec_file (0);
- if (exec_file == NULL)
- exec_file = "";
-
- printf_filtered (_("Detaching from program: %s, %s\n"), exec_file,
- target_pid_to_str (ptid_t (pid)).c_str ());
- }
+ target_announce_detach (from_tty);
do_detach ();
if (!open_procinfo_files (pi, FD_CTL))
{
- fprintf_filtered (gdb_stderr, "procfs:%d -- ", __LINE__);
- xsnprintf (errmsg, sizeof (errmsg),
- "do_attach: couldn't open /proc file for process %d",
- ptid.pid ());
- dead_procinfo (pi, errmsg, NOKILL);
+ int saved_errno = errno;
+ std::string errmsg
+ = string_printf ("procfs:%d -- do_attach: couldn't open /proc "
+ "file for process %d", __LINE__, ptid.pid ());
+ errno = saved_errno;
+ dead_procinfo (pi, errmsg.c_str (), NOKILL);
}
/* Stop the process (if it isn't already stopped). */
inf = current_inferior ();
inferior_appeared (inf, pi->pid);
/* Let GDB know that the inferior was attached. */
- inf->attach_flag = 1;
+ inf->attach_flag = true;
/* Create a procinfo for the current lwp. */
lwpid = proc_get_current_thread (pi);
case PR_SYSENTRY:
if (what == SYS_lwp_exit)
{
- if (print_thread_events)
- printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (retval).c_str ());
- delete_thread (find_thread_ptid (this, retval));
- target_continue_no_signal (ptid);
+ delete_thread (this->find_thread (retval));
+ proc_resume (pi, ptid, 0, GDB_SIGNAL_0);
goto wait_again;
}
else if (what == SYS_exit)
}
else
{
- printf_filtered (_("procfs: trapped on entry to "));
+ gdb_printf (_("procfs: trapped on entry to "));
proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
+ gdb_printf ("\n");
long i, nsysargs, *sysargs;
if (nsysargs > 0 && sysargs != NULL)
{
- printf_filtered (_("%ld syscall arguments:\n"),
- nsysargs);
+ gdb_printf (_("%ld syscall arguments:\n"),
+ nsysargs);
for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ gdb_printf ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
}
- /* How to keep going without returning to wfi: */
- target_continue_no_signal (ptid);
+ proc_resume (pi, ptid, 0, GDB_SIGNAL_0);
goto wait_again;
}
break;
if (!in_thread_list (this, temp_ptid))
add_thread (this, temp_ptid);
- target_continue_no_signal (ptid);
+ proc_resume (pi, ptid, 0, GDB_SIGNAL_0);
goto wait_again;
}
else if (what == SYS_lwp_exit)
{
- if (print_thread_events)
- printf_unfiltered (_("[%s exited]\n"),
- target_pid_to_str (retval).c_str ());
- delete_thread (find_thread_ptid (this, retval));
- status->kind = TARGET_WAITKIND_SPURIOUS;
+ delete_thread (this->find_thread (retval));
+ status->set_spurious ();
return retval;
}
else
{
- printf_filtered (_("procfs: trapped on exit from "));
+ gdb_printf (_("procfs: trapped on exit from "));
proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
+ gdb_printf ("\n");
long i, nsysargs, *sysargs;
if (nsysargs > 0 && sysargs != NULL)
{
- printf_filtered (_("%ld syscall arguments:\n"),
- nsysargs);
+ gdb_printf (_("%ld syscall arguments:\n"),
+ nsysargs);
for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ gdb_printf ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
}
- target_continue_no_signal (ptid);
+ proc_resume (pi, ptid, 0, GDB_SIGNAL_0);
goto wait_again;
}
break;
#else
if (retry < 5)
{
- printf_filtered (_("Retry #%d:\n"), retry);
+ gdb_printf (_("Retry #%d:\n"), retry);
pi->status_valid = 0;
goto wait_again;
}
if (!in_thread_list (this, temp_ptid))
add_thread (this, temp_ptid);
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = GDB_SIGNAL_0;
+ status->set_stopped (GDB_SIGNAL_0);
return retval;
}
#endif
}
break;
default: /* switch (why) unmatched */
- printf_filtered ("procfs:%d -- ", __LINE__);
- printf_filtered (_("child stopped for unknown reason:\n"));
+ gdb_printf ("procfs:%d -- ", __LINE__);
+ gdb_printf (_("child stopped for unknown reason:\n"));
proc_prettyprint_why (why, what, 1);
error (_("... giving up..."));
break;
else /* Flags do not indicate STOPPED. */
{
/* surely this can't happen... */
- printf_filtered ("procfs:%d -- process not stopped.\n",
- __LINE__);
+ gdb_printf ("procfs:%d -- process not stopped.\n",
+ __LINE__);
proc_prettyprint_flags (flags, 1);
error (_("procfs: ...giving up..."));
}
}
if (status)
- store_waitstatus (status, wstat);
+ *status = host_status_to_waitstatus (wstat);
}
return retval;
return 0;
}
-/* Make the child process runnable. Normally we will then call
- procfs_wait and wait for it to stop again (unless gdb is async).
+/* Make child process PI runnable.
If STEP is true, then arrange for the child to stop again after
- executing a single instruction. If SIGNO is zero, then cancel any
- pending signal; if non-zero, then arrange for the indicated signal
- to be delivered to the child when it runs. If PID is -1, then
- allow any child thread to run; if non-zero, then allow only the
- indicated thread to run. (not implemented yet). */
+ executing a single instruction. SCOPE_PTID, STEP and SIGNO are
+ like in the target_resume interface. */
-void
-procfs_target::resume (ptid_t ptid, int step, enum gdb_signal signo)
+static void
+proc_resume (procinfo *pi, ptid_t scope_ptid, int step, enum gdb_signal signo)
{
- procinfo *pi, *thread;
+ procinfo *thread;
int native_signo;
/* FIXME: Check/reword. */
So basically PR_STEP is the sole argument that must be passed
to proc_run_process. */
- /* Find procinfo for main process. */
- pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
-
- /* First cut: ignore pid argument. */
errno = 0;
/* Convert signal to host numbering. */
/* Void the process procinfo's caches. */
invalidate_cache (NULL, pi, NULL);
- if (ptid.pid () != -1)
+ if (scope_ptid.pid () != -1)
{
/* Resume a specific thread, presumably suppressing the
others. */
- thread = find_procinfo (ptid.pid (), ptid.lwp ());
+ thread = find_procinfo (scope_ptid.pid (), scope_ptid.lwp ());
if (thread != NULL)
{
if (thread->tid != 0)
}
}
+/* Implementation of target_ops::resume. */
+
+void
+procfs_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
+{
+ /* Find procinfo for main process. */
+ procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
+
+ proc_resume (pi, scope_ptid, step, signo);
+}
+
/* Set up to trace signals in the child process. */
void
{
struct inferior *inf = current_inferior ();
- printf_filtered (_("\tUsing the running image of %s %s via /proc.\n"),
- inf->attach_flag? "attached": "child",
- target_pid_to_str (inferior_ptid).c_str ());
+ gdb_printf (_("\tUsing the running image of %s %s via /proc.\n"),
+ inf->attach_flag? "attached": "child",
+ target_pid_to_str (ptid_t (inf->pid)).c_str ());
}
/* Make it die. Wait for it to die. Clean up after it. Note: this
pi = create_procinfo (getpid (), 0);
if (pi == NULL)
- perror_with_name (_("procfs: create_procinfo failed in child."));
+ perror_with_name (_("procfs: create_procinfo failed in child"));
if (open_procinfo_files (pi, FD_CTL) == 0)
{
len = p1 - p;
else
len = strlen (p);
- strncpy (tryname, p, len);
+ memcpy (tryname, p, len);
tryname[len] = '\0';
strcat (tryname, "/");
strcat (tryname, shell_file);
shell_file = tryname;
}
- if (!target_is_pushed (this))
- push_target (this);
+ inferior *inf = current_inferior ();
+ if (!inf->target_is_pushed (this))
+ inf->push_target (this);
pid = fork_inferior (exec_file, allargs, env, procfs_set_exec_trap,
NULL, procfs_pre_trace, shell_file, NULL);
{
ptid_t gdb_threadid = ptid_t (pi->pid, thread->tid, 0);
- thread_info *thr = find_thread_ptid (&the_procfs_target, gdb_threadid);
+ thread_info *thr = the_procfs_target.find_thread (gdb_threadid);
if (thr == NULL || thr->state == THREAD_EXITED)
add_thread (&the_procfs_target, gdb_threadid);
/* Accepts an integer PID; Returns a string representing a file that
can be opened to get the symbols for the child process. */
-char *
+const char *
procfs_target::pid_to_exec_file (int pid)
{
static char buf[PATH_MAX];
procfs_address_to_host_pointer will reveal that an internal error
will be generated when the host and target pointer sizes are
different. */
- struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ struct type *ptr_type
+ = builtin_type (current_inferior ()->arch ())->builtin_data_ptr;
- if (sizeof (void *) != TYPE_LENGTH (ptr_type))
+ if (sizeof (void *) != ptr_type->length ())
return 0;
/* Other tests here??? */
struct expression *cond)
{
if (!target_have_steppable_watchpoint ()
- && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch ()))
+ && !gdbarch_have_nonsteppable_watchpoint (current_inferior ()->arch ()))
/* When a hardware watchpoint fires off the PC will be left at
the instruction following the one which caused the
watchpoint. It will *NOT* be necessary for GDB to step over
(map->pr_mflags & MA_WRITE) != 0,
(map->pr_mflags & MA_EXEC) != 0,
1, /* MODIFIED is unknown, pass it as true. */
+ false,
data);
}
pr_off = (unsigned int) map->pr_offset;
- if (gdbarch_addr_bit (target_gdbarch ()) == 32)
- printf_filtered ("\t%#10lx %#10lx %#10lx %#10x %7s\n",
- (unsigned long) map->pr_vaddr,
- (unsigned long) map->pr_vaddr + map->pr_size - 1,
- (unsigned long) map->pr_size,
- pr_off,
- mappingflags (map->pr_mflags));
+ if (gdbarch_addr_bit (current_inferior ()->arch ()) == 32)
+ gdb_printf ("\t%#10lx %#10lx %#10lx %#10x %7s\n",
+ (unsigned long) map->pr_vaddr,
+ (unsigned long) map->pr_vaddr + map->pr_size - 1,
+ (unsigned long) map->pr_size,
+ pr_off,
+ mappingflags (map->pr_mflags));
else
- printf_filtered (" %#18lx %#18lx %#10lx %#10x %7s\n",
- (unsigned long) map->pr_vaddr,
- (unsigned long) map->pr_vaddr + map->pr_size - 1,
- (unsigned long) map->pr_size,
- pr_off,
- mappingflags (map->pr_mflags));
+ gdb_printf (" %#18lx %#18lx %#10lx %#10x %7s\n",
+ (unsigned long) map->pr_vaddr,
+ (unsigned long) map->pr_vaddr + map->pr_size - 1,
+ (unsigned long) map->pr_size,
+ pr_off,
+ mappingflags (map->pr_mflags));
return 0;
}
if (summary)
return; /* No output for summary mode. */
- printf_filtered (_("Mapped address spaces:\n\n"));
- if (gdbarch_ptr_bit (target_gdbarch ()) == 32)
- printf_filtered ("\t%10s %10s %10s %10s %7s\n",
- "Start Addr",
- " End Addr",
- " Size",
- " Offset",
- "Flags");
+ gdb_printf (_("Mapped address spaces:\n\n"));
+ if (gdbarch_ptr_bit (current_inferior ()->arch ()) == 32)
+ gdb_printf ("\t%10s %10s %10s %10s %7s\n",
+ "Start Addr",
+ " End Addr",
+ " Size",
+ " Offset",
+ "Flags");
else
- printf_filtered (" %18s %18s %10s %10s %7s\n",
- "Start Addr",
- " End Addr",
- " Size",
- " Offset",
- "Flags");
+ gdb_printf (" %18s %18s %10s %10s %7s\n",
+ "Start Addr",
+ " End Addr",
+ " Size",
+ " Offset",
+ "Flags");
iterate_over_mappings (pi, NULL, NULL, info_mappings_callback);
- printf_filtered ("\n");
+ gdb_printf ("\n");
}
/* Implement the "info proc" command. */
if (process)
{
- printf_filtered (_("process %d flags:\n"), process->pid);
+ gdb_printf (_("process %d flags:\n"), process->pid);
proc_prettyprint_flags (proc_flags (process), 1);
if (proc_flags (process) & (PR_STOPPED | PR_ISTOP))
proc_prettyprint_why (proc_why (process), proc_what (process), 1);
if (proc_get_nthreads (process) > 1)
- printf_filtered ("Process has %d threads.\n",
- proc_get_nthreads (process));
+ gdb_printf ("Process has %d threads.\n",
+ proc_get_nthreads (process));
}
if (thread)
{
- printf_filtered (_("thread %d flags:\n"), thread->tid);
+ gdb_printf (_("thread %d flags:\n"), thread->tid);
proc_prettyprint_flags (proc_flags (thread), 1);
if (proc_flags (thread) & (PR_STOPPED | PR_ISTOP))
proc_prettyprint_why (proc_why (thread), proc_what (thread), 1);
static int
find_signalled_thread (struct thread_info *info, void *data)
{
- if (info->suspend.stop_signal != GDB_SIGNAL_0
+ if (info->stop_signal () != GDB_SIGNAL_0
&& info->ptid.pid () == inferior_ptid.pid ())
return 1;
iterate_over_threads (find_signalled_thread, NULL);
if (info)
- return info->suspend.stop_signal;
+ return info->stop_signal ();
else
return GDB_SIGNAL_0;
}
char psargs[80] = {'\0'};
procinfo *pi = find_procinfo_or_die (inferior_ptid.pid (), 0);
gdb::unique_xmalloc_ptr<char> note_data;
- const char *inf_args;
enum gdb_signal stop_signal;
if (get_exec_file (0))
strncpy (psargs, get_exec_file (0), sizeof (psargs));
psargs[sizeof (psargs) - 1] = 0;
- inf_args = get_inferior_args ();
- if (inf_args && *inf_args
- && (strlen (inf_args)
- < ((int) sizeof (psargs) - (int) strlen (psargs))))
+ const std::string &inf_args = current_inferior ()->args ();
+ if (!inf_args.empty () &&
+ inf_args.length () < ((int) sizeof (psargs) - (int) strlen (psargs)))
{
strncat (psargs, " ",
sizeof (psargs) - strlen (psargs));
- strncat (psargs, inf_args,
+ strncat (psargs, inf_args.c_str (),
sizeof (psargs) - strlen (psargs));
}
}
stop_signal = find_stop_signal ();
- fill_gregset (get_current_regcache (), &gregs, -1);
+ fill_gregset (get_thread_regcache (inferior_thread ()), &gregs, -1);
note_data.reset (elfcore_write_pstatus (obfd, note_data.release (), note_size,
inferior_ptid.pid (),
stop_signal, &gregs));
proc_iterate_over_threads (pi, procfs_corefile_thread_callback,
&thread_args);
- gdb::optional<gdb::byte_vector> auxv =
- target_read_alloc (current_top_target (), TARGET_OBJECT_AUXV, NULL);
+ std::optional<gdb::byte_vector> auxv =
+ target_read_alloc (current_inferior ()->top_target (),
+ TARGET_OBJECT_AUXV, NULL);
if (auxv && !auxv->empty ())
note_data.reset (elfcore_write_note (obfd, note_data.release (), note_size,
"CORE", NT_AUXV, auxv->data (),