#include "target.h"
#include "wait.h"
#include "gdbcmd.h"
+#include "gdbcore.h"
+#if 0
#include <servers/machid_lib.h>
+#else
+#define MACH_TYPE_TASK 1
+#define MACH_TYPE_THREAD 2
+#endif
/* Included only for signal names and NSIG
*
#define NULL_CLEANUP (struct cleanup *)0
struct cleanup *cleanup_step = NULL_CLEANUP;
+\f
+extern struct target_ops m3_ops;
+static void m3_kill_inferior ();
\f
#if 0
#define MACH_TYPE_EXCEPTION_PORT -1
}
}
else
- mid = 3735928559; /* 0x? :-) */
+ abort ();
new = (port_chain_t) obstack_alloc (port_chain_obstack,
sizeof (struct port_chain));
intercept_exec_calls (exec_counter)
int exec_counter;
{
+ int terminal_initted = 0;
+
struct syscall_msg_t {
mach_msg_header_t header;
mach_msg_type_t type;
original_exec_reply = syscall_in.header.msgh_remote_port;
syscall_in.header.msgh_remote_port = exec_reply_send;
}
+
+ if (!terminal_initted)
+ {
+ /* Now that the child has exec'd we know it has already set its
+ process group. On POSIX systems, tcsetpgrp will fail with
+ EPERM if we try it before the child's setpgid. */
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ terminal_initted = 1;
+ }
+
exec_counter--;
}
if (ret != KERN_SUCCESS)
{
warning ("Can not select a thread from a dead task");
- kill_inferior ();
+ m3_kill_inferior ();
return KERN_FAILURE;
}
CHK ("Could not abort system calls when selecting a thread", ret);
stop_pc = read_pc();
- set_current_frame (create_new_frame (read_register (FP_REGNUM),
- stop_pc));
+ flush_cached_frames ();
select_frame (get_current_frame (), 0);
-
- stop_frame_address = FRAME_FP (get_current_frame ());
}
return KERN_SUCCESS;
{
kern_return_t ret;
+ push_target (&m3_ops);
+
inferior_task = task_by_pid (pid);
if (! MACH_PORT_VALID (inferior_task))
There is no other way to exit this loop.
Returns the inferior_pid for rest of gdb.
- Side effects: Set unix exit value to *w.
- */
+ Side effects: Set *OURSTATUS. */
int
-mach_really_wait (w)
- WAITTYPE *w;
+mach_really_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
{
- int pid;
kern_return_t ret;
+ int w;
struct msg {
mach_msg_header_t header;
{
/* Collect Unix exit status for gdb */
- wait3(w, WNOHANG, 0);
+ wait3(&w, WNOHANG, 0);
/* This mess is here to check that the rest of
* gdb knows that the inferior died. It also
* has happened to it's children when mach-magic
* is applied on them.
*/
- if ((!WIFEXITED(*w) && WIFSTOPPED(*w)) ||
- (WIFEXITED(*w) && WEXITSTATUS(*w) > 0377))
+ if ((!WIFEXITED(w) && WIFSTOPPED(w)) ||
+ (WIFEXITED(w) && WEXITSTATUS(w) > 0377))
{
- WSETEXIT(*w, 0);
+ WSETEXIT(w, 0);
warning ("Using exit value 0 for terminated task");
}
- else if (!WIFEXITED(*w))
+ else if (!WIFEXITED(w))
{
- int sig = WTERMSIG(*w);
+ int sig = WTERMSIG(w);
/* Signals cause problems. Warn the user. */
if (sig != SIGKILL) /* Bad luck if garbage matches this */
warning ("The terminating signal stuff may be nonsense");
else if (sig > NSIG)
{
- WSETEXIT(*w, 0);
+ WSETEXIT(w, 0);
warning ("Using exit value 0 for terminated task");
}
}
+ store_waitstatus (ourstatus, w);
return inferior_pid;
}
}
if (stopped_in_exception)
{
/* Get unix state. May be changed in mach3_exception_actions() */
- wait3(w, WNOHANG, 0);
+ wait3(&w, WNOHANG, 0);
- mach3_exception_actions (w, FALSE, "Task");
+ mach3_exception_actions (&w, FALSE, "Task");
+ store_waitstatus (ourstatus, w);
return inferior_pid;
}
}
return;
}
+#if 0
+/* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
+
/* If ^C is typed when we are waiting for a message
* and your Unix server is able to notice that we
* should quit now.
if (mach_really_waiting)
immediate_quit = 1;
}
+#endif
/*
* Gdb message server.
if (! port_valid (inferior_task, MACH_PORT_TYPE_SEND))
{
- kill_inferior ();
+ m3_kill_inferior ();
error ("Inferior killed (task port invalid)");
}
else
sprintf(buf, "_t%d", id);
}
else
- return (one_cproc->cthread->name);
+ return (char *)(one_cproc->cthread->name);
else
{
if (id < 0)
{
warning ("Error getting inferior's thread list:%s",
mach_error_string(ret));
- kill_inferior ();
+ m3_kill_inferior ();
return -1;
}
int index;
gdb_thread_t scan;
boolean_t all_mapped = TRUE;
+ LONGEST stack_base;
+ LONGEST stack_size;
for (scan = cprocs; scan; scan = scan->next)
{
/* Check if the cproc is found by its stack */
for (index = 0; index < thread_count; index++)
{
- LONGEST stack_base =
- extract_signed_integer (scan.raw_cproc + CPROC_BASE_OFFSET,
+ stack_base =
+ extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
CPROC_BASE_SIZE);
- LONGEST stack_size =
- extract_signed_integer (scan.raw_cproc + CPROC_SIZE_OFFSET,
+ stack_size =
+ extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
CPROC_SIZE_SIZE);
if ((mthreads + index)->sp > stack_base &&
(mthreads + index)->sp <= stack_base + stack_size)
* the user stack pointer saved in the
* emulator.
*/
- if (scan->reverse_map == -1 &&
- usp > scan->stack_base &&
- usp <= scan->stack_base + scan->stack_size)
+ if (scan->reverse_map == -1)
{
- mthread->cproc = scan;
- scan->reverse_map = index;
- break;
+ stack_base =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_BASE_OFFSET,
+ CPROC_BASE_SIZE);
+ stack_size =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_SIZE_OFFSET,
+ CPROC_SIZE_SIZE);
+ if (usp > stack_base &&
+ usp <= stack_base + stack_size)
+ {
+ mthread->cproc = scan;
+ scan->reverse_map = index;
+ break;
+ }
}
}
}
void
print_tl_address (stream, pc)
- FILE *stream;
+ GDB_FILE *stream;
CORE_ADDR pc;
{
if (! lookup_minimal_symbol_by_pc (pc))
if (! symaddr)
{
- msymbol = lookup_minimal_symbol (name, (struct objfile *) NULL);
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol && msymbol->type == mst_data)
- symaddr = msymbol->address;
+ symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
}
return symaddr;
sizeof (struct gdb_thread));
if (!mach3_read_inferior (their_cprocs,
- &cproc_copy.raw_cproc[0],
+ &cproc_copy->raw_cproc[0],
CPROC_SIZE))
error("Can't read next cproc at 0x%x.", their_cprocs);
- cproc_copy = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
their_cprocs =
- extract_address (cproc_copy.raw_cproc + CPROC_LIST_OFFSET,
+ extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
CPROC_LIST_SIZE);
cproc_copy_incarnation =
- extract_address (cproc_copy.raw_cproc + CPROC_INCARNATION_OFFSET,
+ extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
CPROC_INCARNATION_SIZE);
if (cproc_copy_incarnation == (CORE_ADDR)0)
{
int context;
- if (! mthread || !mthread->cproc || !mthread->cproc->context)
+ if (! mthread || !mthread->cproc)
return -1;
context = extract_signed_integer
(mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
CPROC_CONTEXT_SIZE);
+ if (context == 0)
+ return -1;
mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
int mid;
char buf[10];
char slot[3];
+ int cproc_state =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
selected = ' ';
if (ths.flags & TH_FLAGS_IDLE)
strcat (buf, "I");
- /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
printf_filtered (TL_FORMAT,
slot,
mid,
kthread->in_emulator ? "E" : "",
translate_state (ths.run_state),
buf,
- translate_cstate (scan->state),
+ translate_cstate (cproc_state),
wired);
- print_tl_address (stdout, kthread->pc);
+ print_tl_address (gdb_stdout, kthread->pc);
}
else
{
continue; /* EMcM */
#endif
- /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
printf_filtered (TL_FORMAT,
"-",
-neworder, /* Pseudo MID */
"",
"-", /* kernel state */
"",
- translate_cstate (scan->state),
+ translate_cstate (cproc_state),
"");
state.cproc = scan;
if (FETCH_CPROC_STATE (&state) == -1)
puts_filtered ("???");
else
- print_tl_address (stdout, state.pc);
+ print_tl_address (gdb_stdout, state.pc);
neworder++;
}
if (ths.flags & TH_FLAGS_IDLE)
strcat (buf, "I");
- /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
printf_filtered (TL_FORMAT,
slot,
mid,
buf,
"", /* No cproc state */
""); /* Can't be wired */
- print_tl_address (stdout, their_threads[index].pc);
+ print_tl_address (gdb_stdout, their_threads[index].pc);
puts_filtered ("\n");
}
}
if (ret != KERN_SUCCESS)
{
warning ("Could not suspend inferior threads.");
- kill_inferior ();
- return_to_top_level ();
+ m3_kill_inferior ();
+ return_to_top_level (RETURN_ERROR);
}
for (index = 0; index < thread_count; index++)
ret = task_threads (inferior_task, &thread_list, &thread_count);
if (ret != KERN_SUCCESS)
{
- kill_inferior ();
+ m3_kill_inferior ();
error("task_threads", mach_error_string( ret));
}
{
if (current_thread)
current_thread = saved_thread;
- return_to_top_level ();
+ return_to_top_level (RETURN_ERROR);
}
ret = thread_info (current_thread,
if (exception_map[stop_exception].print || force_print)
{
- int giveback = grab_terminal ();
+ target_terminal_ours ();
printf_filtered ("\n%s received %s exception : ",
who,
default:
fatal ("Unknown exception");
}
-
- if (giveback)
- terminal_inferior ();
}
}
\f
char *arg;
int from_tty;
{
- printf ("\"thread\" must be followed by the name of a thread command.\n");
- help_list (cmd_thread_list, "thread ", -1, stdout);
+ printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
+ help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
}
/*ARGSUSED*/
char *arg;
int from_tty;
{
- printf ("\"task\" must be followed by the name of a task command.\n");
- help_list (cmd_task_list, "task ", -1, stdout);
+ printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
+ help_list (cmd_task_list, "task ", -1, gdb_stdout);
}
add_mach_specific_commands ()
{
- extern void condition_thread ();
-
/* Thread handling commands */
/* FIXME: Move our thread support into the generic thread.c stuff so we
add_cmd ("kill", class_run, thread_kill_command,
"Kill the specified thread MID from inferior task.",
&cmd_thread_list);
+#if 0
+ /* The rest of this support (condition_thread) was not merged. It probably
+ should not be merged in this form, but instead added to the generic GDB
+ thread support. */
add_cmd ("break", class_breakpoint, condition_thread,
"Breakpoint N will only be effective for thread MID or @SLOT\n\
If MID/@SLOT is omitted allow all threads to break at breakpoint",
&cmd_thread_list);
+#endif
/* Thread command shorthands (for backward compatibility) */
add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
char *allargs;
char **env;
{
- fork_inferior (exec_file, allargs, env, m3_trace_m3, m3_trace_him);
+ fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL);
/* We are at the first instruction we care about. */
/* Pedal to the metal... */
proceed ((CORE_ADDR) -1, 0, 0);
m3_resume (pid, step, signal)
int pid;
int step;
- int signal;
+ enum target_signal signal;
{
kern_return_t ret;
vm_read_cache_valid = FALSE;
if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
- kill (inferior_pid, signal);
+ kill (inferior_pid, target_signal_to_host (signal));
if (step)
{
exec_file = (char *) get_exec_file (0);
if (exec_file)
- printf ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
+ printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
else
- printf ("Attaching to %s\n", target_pid_to_str (pid));
+ printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
m3_do_attach (pid);
inferior_pid = pid;
- push_target (&procfs_ops);
+ push_target (&m3_ops);
}
\f
void
char *exec_file = get_exec_file (0);
if (exec_file == 0)
exec_file = "";
- printf ("Detaching from program: %s %s\n",
+ printf_unfiltered ("Detaching from program: %s %s\n",
exec_file, target_pid_to_str (inferior_pid));
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
if (args)
siggnal = atoi (args);
}
#endif /* ATTACH_DETACH */
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+m3_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+m3_files_info (ignore)
+ struct target_ops *ignore;
+{
+ /* FIXME: should print MID and all that crap. */
+ printf_unfiltered ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+static void
+m3_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
#ifdef DUMP_SYSCALL
#ifdef __STDC__
#define STR(x) #x
}
#endif DUMP_SYSCALL
+static void
+m3_stop ()
+{
+ error ("to_stop target function not implemented");
+}
+
struct target_ops m3_ops = {
"mach", /* to_shortname */
"Mach child process", /* to_longname */
"Mach child process (started by the \"run\" command).", /* to_doc */
- ??_open, /* to_open */
+ m3_open, /* to_open */
0, /* to_close */
m3_attach, /* to_attach */
m3_detach, /* to_detach */
mach_really_wait, /* to_wait */
fetch_inferior_registers, /* to_fetch_registers */
store_inferior_registers, /* to_store_registers */
- child_prepare_to_store, /* to_prepare_to_store */
+ m3_prepare_to_store, /* to_prepare_to_store */
m3_xfer_memory, /* to_xfer_memory */
-
- /* FIXME: Should print MID and all that crap. */
- child_files_info, /* to_files_info */
-
+ m3_files_info, /* to_files_info */
memory_insert_breakpoint, /* to_insert_breakpoint */
memory_remove_breakpoint, /* to_remove_breakpoint */
terminal_init_inferior, /* to_terminal_init */
m3_mourn_inferior, /* to_mourn_inferior */
m3_can_run, /* to_can_run */
0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ m3_stop, /* to_stop */
process_stratum, /* to_stratum */
0, /* to_next */
1, /* to_has_all_memory */