macosx-nat-inferior-debug.c [plain text]
#include "macosx-nat-inferior-debug.h"
#include "macosx-nat-dyld.h"
#include "macosx-nat-inferior.h"
#include "macosx-nat-mutils.h"
#include "macosx-nat-sigthread.h"
#include "macosx-nat-threads.h"
#include "macosx-xdep.h"
#include "defs.h"
#include "inferior.h"
#include "target.h"
#include "symfile.h"
#include "symtab.h"
#include "objfiles.h"
#include "gdbcmd.h"
#include "gdbcore.h"
#include "gdbthread.h"
#include "bfd.h"
#include <sys/ptrace.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
FILE *inferior_stderr = NULL;
int inferior_debug_flag = 0;
int timestamps_debug_flag = 0;
void inferior_debug (int level, const char *fmt, ...)
{
va_list ap;
if (inferior_debug_flag >= level) {
va_start (ap, fmt);
fprintf (inferior_stderr, "[%d inferior]: ", getpid ());
vfprintf (inferior_stderr, fmt, ap);
va_end (ap);
fflush (inferior_stderr);
}
}
const char *unparse_exception_type (unsigned int i)
{
switch (i) {
case EXC_BAD_ACCESS: return "EXC_BAD_ACCESS";
case EXC_BAD_INSTRUCTION: return "EXC_BAD_INSTRUCTION";
case EXC_ARITHMETIC: return "EXC_ARITHMETIC";
case EXC_EMULATION: return "EXC_EMULATION";
case EXC_SOFTWARE: return "EXC_SOFTWARE";
case EXC_BREAKPOINT: return "EXC_BREAKPOINT";
case EXC_SYSCALL: return "EXC_SYSCALL";
case EXC_MACH_SYSCALL: return "EXC_MACH_SYSCALL";
case EXC_RPC_ALERT: return "EXC_RPC_ALERT";
default:
return "???";
}
}
const char *unparse_protection (vm_prot_t p)
{
switch (p) {
case VM_PROT_NONE: return "---";
case VM_PROT_READ: return "r--";
case VM_PROT_WRITE: return "-w-";
case VM_PROT_READ | VM_PROT_WRITE: return "rw-";
case VM_PROT_EXECUTE: return "--x";
case VM_PROT_EXECUTE | VM_PROT_READ: return "r-x";
case VM_PROT_EXECUTE | VM_PROT_WRITE: return "-wx";
case VM_PROT_EXECUTE | VM_PROT_WRITE | VM_PROT_READ: return "rwx";
default:
return "???";
}
}
const char *unparse_inheritance (vm_inherit_t i)
{
switch (i) {
case VM_INHERIT_SHARE: return "share";
case VM_INHERIT_COPY: return "copy";
case VM_INHERIT_NONE: return "none";
default:
return "???";
}
}
void macosx_debug_region (task_t task, vm_address_t address)
{
macosx_debug_regions (task, address, 1);
}
void macosx_debug_regions (task_t task, vm_address_t address, int max)
{
kern_return_t kret;
struct vm_region_basic_info info, prev_info;
vm_address_t prev_address;
vm_size_t size, prev_size;
mach_port_t object_name;
mach_msg_type_number_t count;
int nsubregions = 0;
int num_printed = 0;
count = VM_REGION_BASIC_INFO_COUNT;
kret = vm_region (task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t) &info, &count, &object_name);
if (kret != KERN_SUCCESS)
{
printf_filtered ("No memory regions.");
return;
}
memcpy (&prev_info, &info, sizeof (struct vm_region_basic_info));
prev_address = address;
prev_size = size;
nsubregions = 1;
for (;;)
{
int print = 0;
int done = 0;
address = prev_address + prev_size;
if (address == 0)
print = done = 1;
if (! done)
{
count = VM_REGION_BASIC_INFO_COUNT;
kret = vm_region (task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t) &info, &count, &object_name);
if (kret != KERN_SUCCESS)
{
size = 0;
print = done = 1;
}
}
if (address != prev_address + prev_size)
print = 1;
if ((info.protection != prev_info.protection)
|| (info.max_protection != prev_info.max_protection)
|| (info.inheritance != prev_info.inheritance)
|| (info.shared != prev_info.reserved)
|| (info.reserved != prev_info.reserved))
print = 1;
if (print)
{
if (num_printed == 0)
printf_filtered ("Region ");
else
printf_filtered (" ... ");
printf_filtered ("from 0x%lx to 0x%lx (%s, max %s; %s, %s, %s)",
(unsigned long) prev_address,
(unsigned long) prev_address + prev_size,
unparse_protection (prev_info.protection),
unparse_protection (prev_info.max_protection),
unparse_inheritance (prev_info.inheritance),
prev_info.shared ? "shared" : "private",
prev_info.reserved ? "reserved" : "not-reserved");
if (nsubregions > 1)
printf_filtered (" (%d sub-regions)", nsubregions);
printf_filtered ("\n");
prev_address = address;
prev_size = size;
memcpy (&prev_info, &info, sizeof (struct vm_region_basic_info));
nsubregions = 1;
num_printed++;
}
else
{
prev_size += size;
nsubregions++;
}
if ((max > 0) && (num_printed >= max))
done = 1;
if (done)
break;
}
}
void macosx_debug_port_info (task_t task, port_t port)
{
#if 0
kern_return_t kret;
mach_port_status_t status;
kret = mach_port_get_receive_status (task, port, &status);
MACH_CHECK_ERROR (kret);
printf_unfiltered ("Port 0x%lx in task 0x%lx:\n", (unsigned long) port, (unsigned long) task);
printf_unfiltered (" port set: 0x%lx\n", status.mps_pset);
printf_unfiltered (" seqno: 0x%lx\n", status.mps_seqno);
printf_unfiltered (" mscount: 0x%lx\n", status.mps_mscount);
printf_unfiltered (" qlimit: 0x%lx\n", status.mps_qlimit);
printf_unfiltered (" msgcount: 0x%lx\n", status.mps_msgcount);
printf_unfiltered (" sorights: 0x%lx\n", status.mps_sorights);
printf_unfiltered (" srights: 0x%lx\n", status.mps_srights);
printf_unfiltered (" pdrequest: 0x%lx\n", status.mps_pdrequest);
printf_unfiltered (" nsrequest: 0x%lx\n", status.mps_nsrequest);
printf_unfiltered (" flags: 0x%lx\n", status.mps_flags);
#endif
}
void macosx_debug_task_port_info (mach_port_t task)
{
#if 0
kern_return_t ret;
unsigned int i;
port_name_array_t names;
port_type_array_t types;
unsigned int nnames, ntypes;
if (! inferior_debug_flag) { return; }
ret = port_names (task, &names, &nnames, &types, &ntypes);
MACH_WARN_ERROR (ret);
if (ret != KERN_SUCCESS) { return; }
CHECK_FATAL (nnames == ntypes);
fprintf (inferior_stderr, "macosx_debug_task_port_info: ports for task 0x%lx:\n", (long) task);
for (i = 0; i < nnames; i++) {
char *s = NULL;
switch (types[i]) {
case PORT_TYPE_SEND: s = "SEND"; break;
case PORT_TYPE_RECEIVE_OWN: s = "RECEIVE_OWN"; break;
case PORT_TYPE_SET: s = "SET"; break;
default: s = "[UNKNOWN]"; break;
}
fprintf (inferior_stderr, " 0x%lx: %s\n", (long) names[i], s);
}
ret = vm_deallocate (task_self(), (vm_address_t) names, nnames * sizeof (port_name_t));
MACH_WARN_ERROR (ret);
ret = vm_deallocate (task_self(), (vm_address_t) types, ntypes * sizeof (port_type_t));
MACH_WARN_ERROR (ret);
#endif
}
void macosx_debug_inferior_status (macosx_inferior_status *s)
{
kern_return_t ret;
thread_array_t thread_list;
unsigned int thread_count;
unsigned int i;
fprintf (inferior_stderr, "macosx_debug_inferior_status: current status:\n");
fprintf (inferior_stderr, " inferior task: 0x%lx\n", (unsigned long) s->task);
macosx_signal_thread_debug (inferior_stderr, &s->signal_status);
fprintf (inferior_stderr, "macosx_debug_inferior_status: information on debugger task:\n");
macosx_debug_task_port_info (mach_task_self ());
fprintf (inferior_stderr, "macosx_debug_inferior_status: information on inferior task:\n");
macosx_debug_task_port_info (s->task);
fprintf (inferior_stderr, "macosx_debug_inferior_status: information on debugger threads:\n");
ret = task_threads (mach_task_self(), &thread_list, &thread_count);
MACH_CHECK_ERROR (ret);
for (i = 0; i < thread_count; i++) {
fprintf (inferior_stderr, " thread: 0x%lx\n", (long) thread_list[i]);
}
ret = vm_deallocate (mach_task_self(), (vm_address_t) thread_list,
(vm_size_t) (thread_count * sizeof (thread_t)));
MACH_CHECK_ERROR (ret);
fprintf (inferior_stderr, "macosx_debug_inferior_status: information on inferior threads:\n");
ret = task_threads (s->task, &thread_list, &thread_count);
MACH_CHECK_ERROR (ret);
for (i = 0; i < thread_count; i++) {
fprintf (inferior_stderr, " thread: 0x%lx\n", (long) thread_list[i]);
}
ret = vm_deallocate (mach_task_self(), (vm_address_t) thread_list,
(vm_size_t) (thread_count * sizeof (thread_t)));
MACH_CHECK_ERROR (ret);
fflush(inferior_stderr);
}
void macosx_debug_message (mach_msg_header_t *msg)
{
if (! inferior_debug_flag) { return; }
fprintf (inferior_stderr, "[%d inferior]: macosx_debug_message: message contents:\n", getpid ());
fprintf (inferior_stderr, " msgh_bits: 0x%lx\n", (long) msg->msgh_bits);
fprintf (inferior_stderr, " msgh_size: 0x%lx\n", (long) msg->msgh_size);
fprintf (inferior_stderr, " msgh_remote_port: 0x%lx\n", (long) msg->msgh_remote_port);
fprintf (inferior_stderr, " msgh_local_port: 0x%lx\n", (long) msg->msgh_local_port);
fprintf (inferior_stderr, " msgh_reserved: 0x%lx\n", (long) msg->msgh_reserved);
fprintf (inferior_stderr, " msgh_id: 0x%lx\n", (long) msg->msgh_id);
}
void macosx_debug_notification_message (struct macosx_inferior_status *inferior, mach_msg_header_t *msg)
{
if (msg->msgh_id == MACH_NOTIFY_PORT_DELETED) {
mach_port_deleted_notification_t *dmsg = (mach_port_deleted_notification_t *) msg;
if (dmsg->not_port == inferior->task) {
inferior_debug (2, "macosx_process_message: deletion message for task port 0x%lx\n",
(unsigned long) dmsg->not_port);
} else {
inferior_debug (2, "macosx_process_message: deletion message for unknown port 0x%lx; ignoring\n",
(unsigned long) dmsg->not_port);
}
} else {
warning ("macosx_process_message: unknown notification type 0x%lx; ignoring",
(unsigned long) msg->msgh_id);
}
}
void
_initialize_macosx_inferior_debug ()
{
struct cmd_list_element *cmd;
cmd = add_set_cmd ("timestamps", class_obscure, var_boolean,
(char *) ×tamps_debug_flag,
"Set if GDB print timestamps before any terminal output.",
&setdebuglist);
add_show_from_set (cmd, &showdebuglist);
cmd = add_set_cmd ("inferior", class_obscure, var_zinteger,
(char *) &inferior_debug_flag,
"Set if printing inferior communication debugging statements.",
&setdebuglist);
add_show_from_set (cmd, &showdebuglist);
}