/* Interface GDB to the GNU Hurd.
- Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This file is part of GDB.
Boston, MA 02111-1307, USA.
*/
+#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
-#include <string.h>
+#include "gdb_string.h"
#include <sys/ptrace.h>
#include <mach.h>
#include "gdbcore.h"
#include "gdbthread.h"
#include "gdb_assert.h"
+#include "gdb_obstack.h"
#include "gnu-nat.h"
void inf_steal_exc_ports (struct inf *inf);
void inf_restore_exc_ports (struct inf *inf);
struct proc *inf_tid_to_proc (struct inf *inf, int tid);
-inline void inf_set_threads_resume_sc (struct inf *inf,
- struct proc *run_thread,
- int run_others);
-inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
-inline void inf_suspend (struct inf *inf);
-inline void inf_resume (struct inf *inf);
+void inf_set_threads_resume_sc (struct inf *inf,
+ struct proc *run_thread,
+ int run_others);
+int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
+void inf_suspend (struct inf *inf);
+void inf_resume (struct inf *inf);
void inf_set_step_thread (struct inf *inf, struct proc *proc);
void inf_detach (struct inf *inf);
void inf_attach (struct inf *inf, int pid);
proc_debug (proc, "is %s", err ? "dead" : running ? "running" : "suspended");
if (err)
- proc_debug (proc, "err = %s", strerror (err));
+ proc_debug (proc, "err = %s", safe_strerror (err));
if (running)
{
proc->exc_port = exc_port;
else
warning ("Error setting exception port for %s: %s",
- proc_string (proc), strerror (err));
+ proc_string (proc), safe_strerror (err));
}
}
proc->exc_port = MACH_PORT_NULL;
else
warning ("Error setting exception port for %s: %s",
- proc_string (proc), strerror (err));
+ proc_string (proc), safe_strerror (err));
}
}
&prev_port);
if (err)
warning ("Couldn't request notification for port %d: %s",
- port, strerror (err));
+ port, safe_strerror (err));
else
{
proc_debug (proc, "notifications to: %d", inf->event_port);
err = mach_port_allocate (mach_task_self (),
MACH_PORT_RIGHT_RECEIVE, &inf->event_port);
if (err)
- error ("Error allocating event port: %s", strerror (err));
+ error ("Error allocating event port: %s", safe_strerror (err));
/* Make a send right for it, so we can easily copy it for other people. */
mach_port_insert_right (mach_task_self (), inf->event_port,
{
error_t err = proc_pid2task (proc_server, pid, &task_port);
if (err)
- error ("Error getting task for pid %d: %s", pid, strerror (err));
+ error ("Error getting task for pid %d: %s", pid, safe_strerror (err));
}
inf_debug (inf, "setting task: %d", task_port);
}
else if (err)
warning ("Can't modify tracing state for pid %d: %s",
- inf->pid, strerror (err));
+ inf->pid, safe_strerror (err));
else
inf->traced = on;
}
/* The current thread we're considering. */
struct proc *thread = inf->threads;
- bzero (matched, sizeof (matched));
+ memset (matched, 0, sizeof (matched));
while (thread)
{
\f
/* Makes sure that INF's thread list is synced with the actual process. */
-inline int
+int
inf_update_procs (struct inf *inf)
{
if (!inf->task)
/* Sets the resume_sc of each thread in inf. That of RUN_THREAD is set to 0,
and others are set to their run_sc if RUN_OTHERS is true, and otherwise
their pause_sc. */
-inline void
+void
inf_set_threads_resume_sc (struct inf *inf,
struct proc *run_thread, int run_others)
{
\f
/* Cause INF to continue execution immediately; individual threads may still
be suspended (but their suspend counts will be updated). */
-inline void
+void
inf_resume (struct inf *inf)
{
struct proc *thread;
/* Cause INF to stop execution immediately; individual threads may still
be running. */
-inline void
+void
inf_suspend (struct inf *inf)
{
struct proc *thread;
/* Set up the thread resume_sc's so that only the signal thread is running
(plus whatever other thread are set to always run). Returns true if we
did so, or false if we can't find a signal thread. */
-inline int
+int
inf_set_threads_resume_sc_for_signal_thread (struct inf *inf)
{
if (inf->signal_thread)
/* Can't do too much... */
warning ("Can't deliver signal %s: No signal thread.", NAME);
else if (err)
- warning ("Delivering signal %s: %s", NAME, strerror (err));
+ warning ("Delivering signal %s: %s", NAME, safe_strerror (err));
#undef NAME
}
}
if (err)
- warning ("Can't continue process: %s", strerror (err));
+ warning ("Can't continue process: %s", safe_strerror (err));
}
\f
err =
proc_wait_request (proc_server, inf->event_port, inf->pid, WUNTRACED);
if (err)
- warning ("wait request failed: %s", strerror (err));
+ warning ("wait request failed: %s", safe_strerror (err));
else
{
inf_debug (inf, "waits pending: %d", proc_waits_pending);
if (err == EMACH_RCV_INTERRUPTED)
inf_debug (inf, "interrupted");
else if (err)
- error ("Couldn't wait for an event: %s", strerror (err));
+ error ("Couldn't wait for an event: %s", safe_strerror (err));
else
{
struct
if (reply.err)
error ("Handling event, msgid = %d: %s",
- msg.hdr.msgh_id, strerror (reply.err));
+ msg.hdr.msgh_id, safe_strerror (reply.err));
}
if (inf->pending_execs)
error_t
do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t count)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("do_mach_notify_no_senders");
}
error_t
do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("do_mach_notify_port_deleted");
}
error_t
do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("do_mach_notify_msg_accepted");
}
error_t
do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("do_mach_notify_port_destroyed");
}
error_t
do_mach_notify_send_once (mach_port_t notify)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("do_mach_notify_send_once");
}
\f
struct inf *inf = waiting_inf;
inf_debug (inf, "err = %s, pid = %d, status = 0x%x, sigcode = %d",
- err ? strerror (err) : "0", pid, status, sigcode);
+ err ? safe_strerror (err) : "0", pid, status, sigcode);
if (err && proc_wait_pid && (!inf->task || !inf->task->port))
/* Ack. The task has died, but the task-died notification code didn't
{
if (err != EINTR)
{
- warning ("Can't wait for pid %d: %s", inf->pid, strerror (err));
+ warning ("Can't wait for pid %d: %s", inf->pid, safe_strerror (err));
inf->no_wait = 1;
/* Since we can't see the inferior's signals, don't trap them. */
S_proc_setmsgport_reply (mach_port_t reply, error_t err,
mach_port_t old_msg_port)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("S_proc_setmsgport_reply");
}
error_t
S_proc_getmsgport_reply (mach_port_t reply, error_t err, mach_port_t msg_port)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("S_proc_getmsgport_reply");
}
\f
inf->wait.status.value.sig = TARGET_SIGNAL_0;
}
else if (err)
- warning ("Signal delivery failed: %s", strerror (err));
+ warning ("Signal delivery failed: %s", safe_strerror (err));
if (err)
/* We only get this reply when we've posted a signal to a process which we
error_t
S_msg_sig_post_reply (mach_port_t reply, error_t err)
{
- return ill_rpc (__FUNCTION__);
+ return ill_rpc ("S_msg_sig_post_reply");
}
\f
}
static char *
-gnu_pid_to_exec_file (void)
+gnu_pid_to_exec_file (int pid)
{
error ("to_pid_to_exec_file target function not implemented");
return NULL;
err = hurd_safe_copyin (myaddr, (void *) addr - low_address + copied, length);
if (err)
{
- warning ("Read from inferior faulted: %s", strerror (err));
+ warning ("Read from inferior faulted: %s", safe_strerror (err));
length = 0;
}
err = vm_deallocate (mach_task_self (), copied, copy_count);
if (err)
- warning ("gnu_read_inferior vm_deallocate failed: %s", strerror (err));
+ warning ("gnu_read_inferior vm_deallocate failed: %s", safe_strerror (err));
return length;
}
else
{
inf_debug (current_inferior, "%s %p[%d] %s %p",
- write ? "writing" : "reading", memaddr, len,
+ write ? "writing" : "reading", (void *) memaddr, len,
write ? "<--" : "-->", myaddr);
if (write)
return gnu_write_inferior (task, memaddr, myaddr, len);
}
}
+/* Call FUNC on each memory region in the task. */
+static int
+gnu_find_memory_regions (int (*func) (CORE_ADDR,
+ unsigned long,
+ int, int, int,
+ void *),
+ void *data)
+{
+ error_t err;
+ task_t task;
+ vm_address_t region_address, last_region_address, last_region_end;
+ vm_prot_t last_protection;
+
+ if (current_inferior == 0 || current_inferior->task == 0)
+ return 0;
+ task = current_inferior->task->port;
+ if (task == MACH_PORT_NULL)
+ return 0;
+
+ region_address = last_region_address = last_region_end = VM_MIN_ADDRESS;
+ last_protection = VM_PROT_NONE;
+ while (region_address < VM_MAX_ADDRESS)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = VM_MAX_ADDRESS - region_address;
+ vm_address_t old_address = region_address;
+
+ err = vm_region (task,
+ ®ion_address,
+ ®ion_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ if (err == KERN_NO_SPACE)
+ break;
+ if (err != KERN_SUCCESS)
+ {
+ warning ("vm_region failed: %s", mach_error_string (err));
+ return -1;
+ }
+
+ if (protection == last_protection && region_address == last_region_end)
+ /* This region is contiguous with and indistinguishable from
+ the previous one, so we just extend that one. */
+ last_region_end = region_address += region_length;
+ else
+ {
+ /* This region is distinct from the last one we saw, so report
+ that previous one. */
+ if (last_protection != VM_PROT_NONE)
+ (*func) (last_region_address,
+ last_region_end - last_region_address,
+ last_protection & VM_PROT_READ,
+ last_protection & VM_PROT_WRITE,
+ last_protection & VM_PROT_EXECUTE,
+ data);
+ last_region_address = region_address;
+ last_region_end = region_address += region_length;
+ last_protection = protection;
+ }
+ }
+
+ /* Report the final region. */
+ if (last_region_end > last_region_address && last_protection != VM_PROT_NONE)
+ (*func) (last_region_address, last_region_end - last_region_address,
+ last_protection & VM_PROT_READ,
+ last_protection & VM_PROT_WRITE,
+ last_protection & VM_PROT_EXECUTE,
+ data);
+
+ return 0;
+}
+
\f
/* Return printable description of proc. */
char *
sprintf (tid_str, "process %d", proc->inf->pid);
else
sprintf (tid_str, "thread %d.%d",
- proc->inf->pid, pid_to_thread_id (proc->tid));
+ proc->inf->pid, pid_to_thread_id (MERGEPID (proc->tid, 0)));
return tid_str;
}
gnu_ops.to_longname = "GNU Hurd process"; /* to_longname */
gnu_ops.to_doc = "GNU Hurd process"; /* to_doc */
gnu_ops.to_open = gnu_open; /* to_open */
- gnu_ops.to_close = 0; /* to_close */
gnu_ops.to_attach = gnu_attach; /* to_attach */
- gnu_ops.to_post_attach = NULL;
- gnu_ops.to_require_attach = NULL; /* to_require_attach */
gnu_ops.to_detach = gnu_detach; /* to_detach */
- gnu_ops.to_require_detach = NULL; /* to_require_detach */
gnu_ops.to_resume = gnu_resume; /* to_resume */
gnu_ops.to_wait = gnu_wait; /* to_wait */
- gnu_ops.to_post_wait = NULL; /* to_post_wait */
gnu_ops.to_fetch_registers = gnu_fetch_registers; /* to_fetch_registers */
gnu_ops.to_store_registers = gnu_store_registers; /* to_store_registers */
gnu_ops.to_prepare_to_store = gnu_prepare_to_store; /* to_prepare_to_store */
gnu_ops.to_xfer_memory = gnu_xfer_memory; /* to_xfer_memory */
- gnu_ops.to_files_info = 0; /* to_files_info */
+ gnu_ops.to_find_memory_regions = gnu_find_memory_regions;
gnu_ops.to_insert_breakpoint = memory_insert_breakpoint;
gnu_ops.to_remove_breakpoint = memory_remove_breakpoint;
gnu_ops.to_terminal_init = gnu_terminal_init_inferior;
gnu_ops.to_terminal_inferior = terminal_inferior;
gnu_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+ gnu_ops.to_terminal_save_ours = terminal_save_ours;
gnu_ops.to_terminal_ours = terminal_ours;
gnu_ops.to_terminal_info = child_terminal_info;
gnu_ops.to_kill = gnu_kill_inferior; /* to_kill */
- gnu_ops.to_load = 0; /* to_load */
- gnu_ops.to_lookup_symbol = 0; /* to_lookup_symbol */
gnu_ops.to_create_inferior = gnu_create_inferior; /* to_create_inferior */
- gnu_ops.to_post_startup_inferior = NULL; /* to_post_startup_inferior */
- /* to_acknowledge_created_inferior */
- gnu_ops.to_acknowledge_created_inferior = NULL;
- /* to_clone_and_follow_inferior */
- gnu_ops.to_clone_and_follow_inferior = NULL;
- /* to_post_follow_inferior_by_clone */
- gnu_ops.to_post_follow_inferior_by_clone = NULL;
- gnu_ops.to_insert_fork_catchpoint = NULL;
- gnu_ops.to_remove_fork_catchpoint = NULL;
- gnu_ops.to_insert_vfork_catchpoint = NULL;
- gnu_ops.to_remove_vfork_catchpoint = NULL;
- gnu_ops.to_has_forked = NULL; /* to_has_forked */
- gnu_ops.to_has_vforked = NULL; /* to_has_vforked */
- gnu_ops.to_can_follow_vfork_prior_to_exec = NULL;
- gnu_ops.to_post_follow_vfork = NULL; /* to_post_follow_vfork */
- gnu_ops.to_insert_exec_catchpoint = NULL;
- gnu_ops.to_remove_exec_catchpoint = NULL;
- gnu_ops.to_has_execd = NULL;
- gnu_ops.to_reported_exec_events_per_exec_call = NULL;
- gnu_ops.to_has_exited = NULL;
gnu_ops.to_mourn_inferior = gnu_mourn_inferior; /* to_mourn_inferior */
gnu_ops.to_can_run = gnu_can_run; /* to_can_run */
- gnu_ops.to_notice_signals = 0; /* to_notice_signals */
gnu_ops.to_thread_alive = gnu_thread_alive; /* to_thread_alive */
gnu_ops.to_pid_to_str = gnu_pid_to_str; /* to_pid_to_str */
gnu_ops.to_stop = gnu_stop; /* to_stop */
gnu_ops.to_pid_to_exec_file = gnu_pid_to_exec_file; /* to_pid_to_exec_file */
gnu_ops.to_stratum = process_stratum; /* to_stratum */
- gnu_ops.DONT_USE = 0; /* to_next */
gnu_ops.to_has_all_memory = 1; /* to_has_all_memory */
gnu_ops.to_has_memory = 1; /* to_has_memory */
gnu_ops.to_has_stack = 1; /* to_has_stack */
gnu_ops.to_has_registers = 1; /* to_has_registers */
gnu_ops.to_has_execution = 1; /* to_has_execution */
- gnu_ops.to_sections = 0; /* sections */
- gnu_ops.to_sections_end = 0; /* sections_end */
gnu_ops.to_magic = OPS_MAGIC; /* to_magic */
} /* init_gnu_ops */
&port, &port_type);
if (err)
error ("Couldn't extract send right %d from inferior: %s",
- name, strerror (err));
+ name, safe_strerror (err));
if (proc->saved_exc_port)
/* Get rid of our reference to the old one. */
proc->exc_port = proc->inf->event_port;
err = proc_set_exception_port (proc, proc->exc_port);
error ("Can't set exception port for %s: %s",
- proc_string (proc), strerror (err));
+ proc_string (proc), safe_strerror (err));
}
}
inf->signal_thread = 0;
else
{
- int tid = thread_id_to_pid (atoi (args));
+ int tid = PIDGET (thread_id_to_pid (atoi (args)));
if (tid < 0)
error ("Thread ID %s not known. Use the \"info threads\" command to\n"
"see the IDs of currently known threads.", args);
info_port_rights (char *args, mach_port_type_t only)
{
struct inf *inf = active_inf ();
- value_ptr vmark = value_mark ();
+ struct value *vmark = value_mark ();
if (args)
/* Explicit list of port rights. */
{
while (*args)
{
- value_ptr val = parse_to_comma_and_eval (&args);
+ struct value *val = parse_to_comma_and_eval (&args);
long right = value_as_long (val);
error_t err =
print_port_info (right, 0, inf->task->port, PORTINFO_DETAILS,
stdout);
if (err)
- error ("%ld: %s.", right, strerror (err));
+ error ("%ld: %s.", right, safe_strerror (err));
}
}
else
print_task_ports_info (inf->task->port, only, PORTINFO_DETAILS,
stdout);
if (err)
- error ("%s.", strerror (err));
+ error ("%s.", safe_strerror (err));
}
value_free_to_mark (vmark);
error_t err =
thread_info (thread->port, THREAD_BASIC_INFO, (int *) &info, &info_len);
if (err)
- error ("%s.", strerror (err));
+ error ("%s.", safe_strerror (err));
thread->sc = info->suspend_count;
if (from_tty)
printf_unfiltered ("Suspend count was %d.\n", thread->sc);
MATTR_CACHE,
&flush);
if (ret != KERN_SUCCESS)
- warning ("Error flushing inferior's cache : %s", strerror (ret));
+ warning ("Error flushing inferior's cache : %s", safe_strerror (ret));
}
#endif /* FLUSH_INFERIOR_CACHE */