/* Machine independent support for QNX Neutrino /proc (process file system)
for GDB. Written by Colin Burgess at QNX Software Systems Limited.
- Copyright (C) 2003-2015 Free Software Foundation, Inc.
+ Copyright (C) 2003-2016 Free Software Foundation, Inc.
Contributed by QNX Software Systems Ltd.
#include <sys/syspage.h>
#include <dirent.h>
#include <sys/netmgr.h>
+#include <sys/auxv.h>
+
#include "gdbcore.h"
#include "inferior.h"
#include "target.h"
return;
}
- num = min (num, num_mapinfos);
+ num = std::min (num, num_mapinfos);
/* Run through the list of mapinfos, and store the data and text info
so we can print it at the bottom of the loop. */
(nodestr != NULL) ? nodestr : "local node");
}
+/* Target to_pid_to_exec_file implementation. */
+
+static char *
+procfs_pid_to_exec_file (struct target_ops *ops, const int pid)
+{
+ int proc_fd;
+ static char proc_path[PATH_MAX];
+ ssize_t rd;
+
+ /* Read exe file name. */
+ snprintf (proc_path, sizeof (proc_path), "%s/proc/%d/exefile",
+ (nodestr != NULL) ? nodestr : "", pid);
+ proc_fd = open (proc_path, O_RDONLY);
+ if (proc_fd == -1)
+ return NULL;
+
+ rd = read (proc_fd, proc_path, sizeof (proc_path) - 1);
+ close (proc_fd);
+ if (rd <= 0)
+ {
+ proc_path[0] = '\0';
+ return NULL;
+ }
+ proc_path[rd] = '\0';
+ return proc_path;
+}
+
/* Attach to process PID, then initialize for debugging it. */
static void
procfs_attach (struct target_ops *ops, const char *args, int from_tty)
static void
interrupt_query (void)
{
- target_terminal_ours ();
-
if (query (_("Interrupted while waiting for the program.\n\
Give up (and stop debugging it)? ")))
{
target_mourn_inferior ();
quit ();
}
-
- target_terminal_inferior ();
}
/* The user typed ^C twice. */
devctl (ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0);
}
+ nto_inferior_data (NULL)->stopped_flags = status.flags;
+ nto_inferior_data (NULL)->stopped_pc = status.ip;
+
if (status.flags & _DEBUG_FLAG_SSTEP)
{
ourstatus->kind = TARGET_WAITKIND_STOPPED;
{
case TARGET_OBJECT_MEMORY:
return procfs_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
+ case TARGET_OBJECT_AUXV:
+ if (readbuf != NULL)
+ {
+ int err;
+ CORE_ADDR initial_stack;
+ debug_process_t procinfo;
+ /* For 32-bit architecture, size of auxv_t is 8 bytes. */
+ const unsigned int sizeof_auxv_t = sizeof (auxv_t);
+ const unsigned int sizeof_tempbuf = 20 * sizeof_auxv_t;
+ int tempread;
+ gdb_byte *const tempbuf = alloca (sizeof_tempbuf);
+
+ if (tempbuf == NULL)
+ return TARGET_XFER_E_IO;
+
+ err = devctl (ctl_fd, DCMD_PROC_INFO, &procinfo,
+ sizeof procinfo, 0);
+ if (err != EOK)
+ return TARGET_XFER_E_IO;
+
+ initial_stack = procinfo.initial_stack;
+
+ /* procfs is always 'self-hosted', no byte-order manipulation. */
+ tempread = nto_read_auxv_from_initial_stack (initial_stack, tempbuf,
+ sizeof_tempbuf,
+ sizeof (auxv_t));
+ tempread = std::min (tempread, len) - offset;
+ memcpy (readbuf, tempbuf + offset, tempread);
+ *xfered_len = tempread;
+ return tempread ? TARGET_XFER_OK : TARGET_XFER_EOF;
+ }
+ /* Fallthru */
default:
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
readbuf, writebuf, offset, len,
int siggnal = 0;
int pid;
- if (from_tty)
- {
- char *exec_file = get_exec_file (0);
- if (exec_file == 0)
- exec_file = "";
- printf_unfiltered ("Detaching from program: %s %s\n",
- exec_file, target_pid_to_str (inferior_ptid));
- gdb_flush (gdb_stdout);
- }
+ target_announce_detach ();
+
if (args)
siggnal = atoi (args);
static int
procfs_remove_breakpoint (struct target_ops *ops, struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
+ struct bp_target_info *bp_tgt,
+ enum remove_bp_reason reason)
{
return procfs_breakpoint (bp_tgt->placed_address, _DEBUG_BREAK_EXEC, -1);
}
t->to_interrupt = procfs_interrupt;
t->to_have_continuable_watchpoint = 1;
t->to_extra_thread_info = nto_extra_thread_info;
+ t->to_pid_to_exec_file = procfs_pid_to_exec_file;
nto_native_ops = t;
static int
procfs_stopped_by_watchpoint (struct target_ops *ops)
{
- return 0;
+ /* NOTE: nto_stopped_by_watchpoint will be called ONLY while we are
+ stopped due to a SIGTRAP. This assumes gdb works in 'all-stop' mode;
+ future gdb versions will likely run in 'non-stop' mode in which case
+ we will have to store/examine statuses per thread in question.
+ Until then, this will work fine. */
+
+ struct inferior *inf = current_inferior ();
+ struct nto_inferior_data *inf_data;
+
+ gdb_assert (inf != NULL);
+
+ inf_data = nto_inferior_data (inf);
+
+ return inf_data->stopped_flags
+ & (_DEBUG_FLAG_TRACE_RD
+ | _DEBUG_FLAG_TRACE_WR
+ | _DEBUG_FLAG_TRACE_MODIFY);
}