/* Target-vector operations for controlling win32 child processes, for GDB.
- Copyright 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
+ Boston, MA 02111-1307, USA. */
/* by Steve Chamberlain, sac@cygnus.com */
#include "target.h"
#include "gdbcore.h"
#include "command.h"
+#include "completer.h"
+#include "regcache.h"
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
/* The ui's event loop. */
-extern int (*ui_loop_hook) PARAMS ((int signo));
+extern int (*ui_loop_hook) (int signo);
/* If we're not using the old Cygwin header file set, define the
following which never should have been in the generic Win32 API
headers in the first place since they were our own invention... */
#ifndef _GNU_H_WINDOWS_H
-#define FLAG_TRACE_BIT 0x100
-#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
+enum
+ {
+ FLAG_TRACE_BIT = 0x100,
+ CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
+ };
#endif
+#include <sys/procfs.h>
+#include <psapi.h>
/* The string sent by cygwin when it processes a signal.
FIXME: This should be in a cygwin include file. */
extern struct target_ops child_ops;
static void child_stop (void);
-static int win32_child_thread_alive (int);
+static int win32_child_thread_alive (ptid_t);
void child_kill_inferior (void);
static int last_sig = 0; /* Set if a signal was received from the
int suspend_count;
CONTEXT context;
STACKFRAME sf;
- } thread_info;
+ }
+thread_info;
static thread_info thread_head;
th->h = h;
th->next = thread_head.next;
thread_head.next = th;
- add_thread (id);
+ add_thread (pid_to_ptid (id));
return th;
}
/* Clear out any old thread list and reintialize it to a
pristine state. */
static void
-child_init_thread_list ()
+child_init_thread_list (void)
{
thread_info *th = &thread_head;
thread_info *here = th->next;
th->next = here->next;
(void) CloseHandle (here->h);
- free (here);
+ xfree (here);
}
}
thread_info *th;
if (info_verbose)
- printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (id));
- delete_thread (id);
+ printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
+ delete_thread (pid_to_ptid (id));
for (th = &thread_head;
th->next != NULL && th->next->id != id;
thread_info *here = th->next;
th->next = here->next;
CloseHandle (here->h);
- free (here);
+ xfree (here);
}
}
long l;
if (r == FCS_REGNUM)
{
- l = *((long *)context_offset) & 0xffff;
+ l = *((long *) context_offset) & 0xffff;
supply_register (r, (char *) &l);
}
else if (r == FOP_REGNUM)
{
- l = (*((long *)context_offset) >> 16) & ((1 << 11) - 1);
+ l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
supply_register (r, (char *) &l);
}
else if (r >= 0)
static void
child_fetch_inferior_registers (int r)
{
- current_thread = thread_rec (inferior_pid, TRUE);
+ current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
do_child_fetch_inferior_registers (r);
}
static void
child_store_inferior_registers (int r)
{
- current_thread = thread_rec (inferior_pid, TRUE);
+ current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
do_child_store_inferior_registers (r);
}
-#include <psapi.h>
static int psapi_loaded = 0;
static HMODULE psapi_module_handle = NULL;
-static BOOL WINAPI (*psapi_EnumProcessModules)(HANDLE, HMODULE*, DWORD, LPDWORD)= NULL;
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD)= NULL;
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD)= NULL;
+static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
+static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
+static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
-int psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+int
+psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
{
DWORD len;
MODULEINFO mi;
int i;
- HMODULE dh_buf [ 1 ];
- HMODULE* DllHandle = dh_buf;
+ HMODULE dh_buf[1];
+ HMODULE *DllHandle = dh_buf;
DWORD cbNeeded;
BOOL ok;
if (!psapi_loaded ||
- psapi_EnumProcessModules == NULL ||
- psapi_GetModuleInformation == NULL ||
- psapi_GetModuleFileNameExA == NULL)
+ psapi_EnumProcessModules == NULL ||
+ psapi_GetModuleInformation == NULL ||
+ psapi_GetModuleFileNameExA == NULL)
{
- if (psapi_loaded)goto failed;
+ if (psapi_loaded)
+ goto failed;
psapi_loaded = 1;
psapi_module_handle = LoadLibrary ("psapi.dll");
if (!psapi_module_handle)
- {
- /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ());*/
- goto failed;
- }
- psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules" );
+ {
+ /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
+ goto failed;
+ }
+ psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
- "GetModuleFileNameExA");
- if (psapi_EnumProcessModules == NULL ||
- psapi_GetModuleInformation == NULL ||
- psapi_GetModuleFileNameExA == NULL)
+ "GetModuleFileNameExA");
+ if (psapi_EnumProcessModules == NULL ||
+ psapi_GetModuleInformation == NULL ||
+ psapi_GetModuleFileNameExA == NULL)
goto failed;
}
cbNeeded = 0;
ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- sizeof (HMODULE),
- &cbNeeded);
+ DllHandle,
+ sizeof (HMODULE),
+ &cbNeeded);
if (!ok || !cbNeeded)
goto failed;
- DllHandle = (HMODULE*) alloca (cbNeeded);
+ DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle)
goto failed;
ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- cbNeeded,
- &cbNeeded);
+ DllHandle,
+ cbNeeded,
+ &cbNeeded);
if (!ok)
goto failed;
for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
{
if (!(*psapi_GetModuleInformation) (current_process_handle,
- DllHandle [i],
- &mi,
- sizeof (mi)))
+ DllHandle[i],
+ &mi,
+ sizeof (mi)))
error ("Can't get module info");
len = (*psapi_GetModuleFileNameExA) (current_process_handle,
- DllHandle [i],
- dll_name_ret,
- MAX_PATH);
+ DllHandle[i],
+ dll_name_ret,
+ MAX_PATH);
if (len == 0)
error ("Error getting dll name: %u\n", GetLastError ());
struct section_addr_info *addrs;
int mainline;
int flags;
+ struct ui_file *err, *out;
struct objfile *ret;
};
+/* Maintain a linked list of "so" information. */
+struct so_stuff
+{
+ struct so_stuff *next, **last;
+ DWORD load_addr;
+ char name[0];
+}
+solib_start, *solib_end;
+
/* Call symbol_file_add with stderr redirected. We don't care if there
are errors. */
static int
safe_symbol_file_add_stub (void *argv)
{
#define p ((struct safe_symbol_file_add_args *)argv)
+ struct so_stuff *so = solib_start.next;
+
+ while ((so = so->next))
+ if (strcasecmp (so->name, p->name) == 0)
+ return 0;
p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
return !!p->ret;
#undef p
/* Restore gdb's stderr after calling symbol_file_add */
static void
-safe_symbol_file_add_cleanup (void *gdb_stderrv)
+safe_symbol_file_add_cleanup (void *p)
{
+#define sp ((struct safe_symbol_file_add_args *)p)
gdb_flush (gdb_stderr);
- ui_file_delete (gdb_stderr);
- gdb_stderr = (struct ui_file *)gdb_stderrv;
+ gdb_flush (gdb_stdout);
+ /* ui_file_delete (gdb_stderr); */
+ ui_file_delete (gdb_stdout);
+ /* gdb_stderr = sp->err; */
+ gdb_stdout = sp->out;
+#undef sp
}
/* symbol_file_add wrapper that prevents errors from being displayed. */
safe_symbol_file_add (char *name, int from_tty,
struct section_addr_info *addrs,
int mainline, int flags)
-
{
struct safe_symbol_file_add_args p;
struct cleanup *cleanup;
- cleanup = make_cleanup (safe_symbol_file_add_cleanup, gdb_stderr);
+ cleanup = make_cleanup (safe_symbol_file_add_cleanup, &p);
+ p.err = gdb_stderr;
+ p.out = gdb_stdout;
gdb_flush (gdb_stderr);
- gdb_stderr = ui_file_new ();
+ gdb_flush (gdb_stdout);
+ /* gdb_stderr = ui_file_new (); */
+ gdb_stdout = ui_file_new ();
p.name = name;
p.from_tty = from_tty;
p.addrs = addrs;
return p.ret;
}
-/* Maintain a linked list of "so" information. */
-struct so_stuff
-{
- struct so_stuff *next, **last;
- DWORD load_addr;
- char name[0];
-} solib_start, *solib_end;
-
/* Remember the maximum DLL length for printing in info dll command. */
int max_dll_name_len;
+static void
+register_loaded_dll (const char *name, DWORD load_addr)
+{
+ struct so_stuff *so;
+ so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (name) + 8 + 2);
+ so->load_addr = load_addr;
+ strcpy (so->name, name);
+
+ solib_end->next = so;
+ solib_end = so;
+ so->next = NULL;
+}
+
/* Wait for child to do something. Return pid of child, or -1 in case
of error; store status through argument pointer OURSTATUS. */
static int
-handle_load_dll (PTR dummy ATTRIBUTE_UNUSED)
+handle_load_dll (void *dummy ATTRIBUTE_UNUSED)
{
LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll;
DWORD dll_name_ptr;
DWORD done;
char dll_buf[MAX_PATH + 1];
- struct so_stuff *so, *solast;
char *dll_name = NULL;
- DWORD dll_base = 0;
int len;
char *p;
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
- dll_buf[0] = dll_buf[sizeof(dll_buf) - 1] = '\0';
+ dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf;
while ((p = strchr (dll_name, '\\')))
*p = '/';
- so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (dll_name) + 8 + 2);
- so->load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
- strcpy (so->name, dll_name);
-
- solib_end->next = so;
- solib_end = so;
- so->next = NULL;
-
+ register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000);
len = strlen (dll_name);
if (len > max_dll_name_len)
max_dll_name_len = len;
/* Return name of last loaded DLL. */
char *
-child_solib_loaded_library_pathname (int pid)
+child_solib_loaded_library_pathname (int pid ATTRIBUTE_UNUSED)
{
- return !solib_end || !solib_end->name[0]? NULL : solib_end->name;
+ return !solib_end || !solib_end->name[0] ? NULL : solib_end->name;
}
/* Clear list of loaded DLLs. */
while ((so = so1) != NULL)
{
so1 = so->next;
- free (so);
+ xfree (so);
}
solib_start.next = NULL;
}
/* Add DLL symbol information. */
-void
-child_solib_add (char *filename, int from_tty, struct target_ops *t)
+static void
+solib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr)
{
struct section_addr_info section_addrs;
the offset from 0 of the first byte in an image - because
of the file header and the section alignment. */
- if (!solib_end || !solib_end->name[0])
+ if (!name || !name[0])
return;
memset (§ion_addrs, 0, sizeof (section_addrs));
section_addrs.other[0].name = ".text";
- section_addrs.other[0].addr = solib_end->load_addr;
- safe_symbol_file_add (solib_end->name, 0, §ion_addrs, 0, OBJF_SHARED);
+ section_addrs.other[0].addr = load_addr;
+ safe_symbol_file_add (name, from_tty, 0, 0, OBJF_SHARED);
return;
}
/* Load DLL symbol info. */
void
-dll_symbol_command (char *args, int from_tty)
+dll_symbol_command (char *args, int from_tty ATTRIBUTE_UNUSED)
{
- struct section_addr_info section_addrs;
-
+ int n;
dont_repeat ();
-
+
if (args == NULL)
error ("dll-symbols requires a file name");
- safe_symbol_file_add (args, 0, NULL, 0, OBJF_SHARED);
-}
+ n = strlen (args);
+ if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
+ {
+ char *newargs = (char *) alloca (n + 4 + 1);
+ strcpy (newargs, args);
+ strcat (newargs, ".dll");
+ args = newargs;
+ }
+
+ safe_symbol_file_add (args, 0, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
+}
/* List currently loaded DLLs. */
void
-info_dll_command (char *ignore, int from_tty)
+info_dll_command (char *ignore ATTRIBUTE_UNUSED, int from_tty ATTRIBUTE_UNUSED)
{
struct so_stuff *so = &solib_start;
printf ("%*s Load Address\n", -max_dll_name_len, "DLL Name");
while ((so = so->next) != NULL)
- printf_unfiltered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
+ printf_filtered ("%*s %08lx\n", -max_dll_name_len, so->name, so->load_addr);
return;
}
ourstatus->kind = TARGET_WAITKIND_STOPPED;
}
- free (s);
+ xfree (s);
return gotasig;
}
/* Record the context of the current thread */
th = thread_rec (current_event.dwThreadId, -1);
- last_sig = 0;
-
switch (code)
{
case EXCEPTION_ACCESS_VIOLATION:
DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_SEGV;
last_sig = SIGSEGV;
break;
case STATUS_FLOAT_OVERFLOW:
case STATUS_INTEGER_DIVIDE_BY_ZERO:
DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_FPE;
last_sig = SIGFPE;
break;
case STATUS_STACK_OVERFLOW:
DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_SEGV;
break;
case EXCEPTION_BREAKPOINT:
DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case DBG_CONTROL_C:
DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_INT;
last_sig = SIGINT; /* FIXME - should check pass state */
break;
case EXCEPTION_SINGLE_STEP:
DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_TRAP;
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08lx\n",
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress));
ourstatus->value.sig = TARGET_SIGNAL_ILL;
last_sig = SIGILL;
break;
default:
+ if (current_event.u.Exception.dwFirstChance)
+ return 0;
printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
current_event.u.Exception.ExceptionRecord.ExceptionCode,
- (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+ (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
break;
}
static int
get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
{
- int breakout = 0;
BOOL debug_event;
DWORD continue_status, event_code;
thread_info *th = NULL;
static thread_info dummy_thread_info;
int retval = 0;
+ last_sig = 0;
+
if (!(debug_event = WaitForDebugEvent (¤t_event, 1000)))
goto out;
current_event.u.CreateThread.hThread);
if (info_verbose)
printf_unfiltered ("[New %s]\n",
- target_pid_to_str (current_event.dwThreadId));
+ target_pid_to_str (
+ pid_to_ptid (current_event.dwThreadId)));
retval = current_event.dwThreadId;
break;
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"CREATE_PROCESS_DEBUG_EVENT"));
+ CloseHandle (current_event.u.CreateProcessInfo.hFile);
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
- main_thread_id = inferior_pid = current_event.dwThreadId;
+ main_thread_id = current_event.dwThreadId;
/* Add the main thread */
+#if 0
th = child_add_thread (current_event.dwProcessId,
current_event.u.CreateProcessInfo.hProcess);
- th = child_add_thread (inferior_pid,
+#endif
+ th = child_add_thread (main_thread_id,
current_event.u.CreateProcessInfo.hThread);
- retval = ourstatus->value.related_pid = current_event.dwProcessId;
+ retval = ourstatus->value.related_pid = current_event.dwThreadId;
break;
case EXIT_PROCESS_DEBUG_EVENT:
ourstatus->kind = TARGET_WAITKIND_EXITED;
ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
CloseHandle (current_process_handle);
- retval = current_event.dwProcessId;
+ retval = main_thread_id;
break;
case LOAD_DLL_DEBUG_EVENT:
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"LOAD_DLL_DEBUG_EVENT"));
+ CloseHandle (current_event.u.LoadDll.hFile);
catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
registers_changed (); /* mark all regs invalid */
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
- retval = current_event.dwProcessId;
+ retval = main_thread_id;
break;
case UNLOAD_DLL_DEBUG_EVENT:
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"EXCEPTION_DEBUG_EVENT"));
- handle_exception (ourstatus);
- retval = current_event.dwThreadId;
+ if (handle_exception (ourstatus))
+ retval = current_event.dwThreadId;
break;
case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"OUTPUT_DEBUG_STRING_EVENT"));
- if (handle_output_debug_string ( ourstatus))
- retval = current_event.dwProcessId;
+ if (handle_output_debug_string (ourstatus))
+ retval = main_thread_id;
break;
+
default:
printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
(DWORD) current_event.dwProcessId,
if (!retval)
CHECK (child_continue (continue_status, -1));
else
- current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
+ {
+ current_thread = th ? : thread_rec (current_event.dwThreadId, TRUE);
+ inferior_ptid = pid_to_ptid (retval);
+ }
out:
return retval;
}
/* Wait for interesting events to occur in the target process. */
-static int
-child_wait (int pid, struct target_waitstatus *ourstatus)
+static ptid_t
+child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
+ int pid = PIDGET (ptid);
+
/* We loop when we get a non-standard exception rather than return
with a SPURIOUS because resume can try and step or modify things,
which needs a current_thread->h. But some of these exceptions mark
{
int retval = get_child_debug_event (pid, ourstatus);
if (retval)
- return retval;
+ return pid_to_ptid (retval);
else
{
int detach = 0;
}
}
+static void
+do_initial_child_stuff (DWORD pid)
+{
+ extern int stop_after_trap;
+
+ last_sig = 0;
+ event_count = 0;
+ exception_count = 0;
+ current_event.dwProcessId = pid;
+ memset (¤t_event, 0, sizeof (current_event));
+ push_target (&child_ops);
+ child_init_thread_list ();
+ child_clear_solibs ();
+ clear_proceed_status ();
+ init_wait_for_inferior ();
+
+ target_terminal_init ();
+ target_terminal_inferior ();
+
+ while (1)
+ {
+ stop_after_trap = 1;
+ wait_for_inferior ();
+ if (stop_signal != TARGET_SIGNAL_TRAP)
+ resume (0, stop_signal);
+ else
+ break;
+ }
+ stop_after_trap = 0;
+ return;
+}
+
/* Attach to process PID, then initialize for debugging it. */
static void
-child_attach (args, from_tty)
- char *args;
- int from_tty;
+child_attach (char *args, int from_tty)
{
BOOL ok;
+ DWORD pid;
if (!args)
error_no_arg ("process-id to attach");
- current_event.dwProcessId = strtoul (args, 0, 0);
-
- ok = DebugActiveProcess (current_event.dwProcessId);
+ pid = strtoul (args, 0, 0);
+ ok = DebugActiveProcess (pid);
if (!ok)
error ("Can't attach to process.");
- exception_count = 0;
- event_count = 0;
-
- child_init_thread_list ();
- child_clear_solibs ();
-
if (from_tty)
{
char *exec_file = (char *) get_exec_file (0);
if (exec_file)
printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
- target_pid_to_str (current_event.dwProcessId));
+ target_pid_to_str (pid_to_ptid (pid)));
else
printf_unfiltered ("Attaching to %s\n",
- target_pid_to_str (current_event.dwProcessId));
+ target_pid_to_str (pid_to_ptid (pid)));
gdb_flush (gdb_stdout);
}
- push_target (&child_ops);
+ do_initial_child_stuff (pid);
+ target_terminal_ours ();
}
static void
if (exec_file == 0)
exec_file = "";
printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
- target_pid_to_str (inferior_pid));
+ target_pid_to_str (inferior_ptid));
gdb_flush (gdb_stdout);
}
- inferior_pid = 0;
+ inferior_ptid = null_ptid;
unpush_target (&child_ops);
}
child_files_info (struct target_ops *ignore ATTRIBUTE_UNUSED)
{
printf_unfiltered ("\tUsing the running image of %s %s.\n",
- attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
+ attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
}
/* ARGSUSED */
error ("Use the \"run\" command to start a Unix child process.");
}
-/* Start an inferior win32 child process and sets inferior_pid to its pid.
+/* Start an inferior win32 child process and sets inferior_ptid to its pid.
EXEC_FILE is the file to run.
ALLARGS is a string containing the arguments to the program.
ENV is the environment vector to pass. Errors reported with error(). */
static void
-child_create_inferior (exec_file, allargs, env)
- char *exec_file;
- char *allargs;
- char **env;
+child_create_inferior (char *exec_file, char *allargs, char **env)
{
char real_path[MAXPATHLEN];
char *winenv;
int i;
STARTUPINFO si;
PROCESS_INFORMATION pi;
- struct target_waitstatus dummy;
BOOL ret;
DWORD flags;
char *args;
- extern int stop_after_trap;
if (!exec_file)
error ("No executable specified, use `target exec'.\n");
if (!ret)
error ("Error creating process %s, (error %d)\n", exec_file, GetLastError ());
- exception_count = 0;
- event_count = 0;
-
- current_process_handle = pi.hProcess;
- current_event.dwProcessId = pi.dwProcessId;
- memset (¤t_event, 0, sizeof (current_event));
- inferior_pid = current_event.dwThreadId = pi.dwThreadId;
- push_target (&child_ops);
- child_init_thread_list ();
- child_clear_solibs ();
- clear_proceed_status ();
- init_wait_for_inferior ();
- target_terminal_init ();
- target_terminal_inferior ();
- last_sig = 0;
+ CloseHandle (pi.hThread);
+ CloseHandle (pi.hProcess);
+ do_initial_child_stuff (pi.dwProcessId);
- while (1)
- {
- stop_after_trap = 1;
- wait_for_inferior ();
- if (stop_signal != TARGET_SIGNAL_TRAP)
- resume (0, stop_signal);
- else
- break;
- }
- stop_after_trap = 0;
-
- /* child_continue (DBG_CONTINUE, -1);*/
+ /* child_continue (DBG_CONTINUE, -1); */
proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
}
static void
-child_mourn_inferior ()
+child_mourn_inferior (void)
{
(void) child_continue (DBG_CONTINUE, -1);
unpush_target (&child_ops);
^C on the controlling terminal. */
static void
-child_stop ()
+child_stop (void)
{
DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
int
child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
- int write, struct target_ops *target ATTRIBUTE_UNUSED)
+ int write, struct mem_attrib *mem ATTRIBUTE_UNUSED,
+ struct target_ops *target ATTRIBUTE_UNUSED)
{
DWORD done;
if (write)
}
void
-child_resume (int pid, int step, enum target_signal sig)
+child_resume (ptid_t ptid, int step, enum target_signal sig)
{
thread_info *th;
DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
- DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+ DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+ int pid = PIDGET (ptid);
last_sig = 0;
}
static void
-child_prepare_to_store ()
+child_prepare_to_store (void)
{
/* Do nothing, since we can store individual regs */
}
static int
-child_can_run ()
+child_can_run (void)
{
return 1;
}
static void
-child_close ()
+child_close (int x ATTRIBUTE_UNUSED)
{
- DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
+ DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
+ PIDGET (inferior_ptid)));
}
struct target_ops child_ops;
}
void
-_initialize_inftarg ()
+_initialize_inftarg (void)
{
+ struct cmd_list_element *c;
+
init_child_ops ();
- add_com ("dll-symbols", class_files, dll_symbol_command,
- "Load dll library symbols from FILE.");
+ c = add_com ("dll-symbols", class_files, dll_symbol_command,
+ "Load dll library symbols from FILE.");
+ c->completer = filename_completer;
+ auto_solib_add = 1;
add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
- (char *) &new_console,
- "Set creation of new console when creating child process.",
- &setlist),
- &showlist);
+ (char *) &new_console,
+ "Set creation of new console when creating child process.",
+ &setlist),
+ &showlist);
add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
- (char *) &new_group,
- "Set creation of new group when creating child process.",
- &setlist),
- &showlist);
+ (char *) &new_group,
+ "Set creation of new group when creating child process.",
+ &setlist),
+ &showlist);
add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
- (char *) &debug_exec,
- "Set whether to display execution in child process.",
- &setlist),
- &showlist);
+ (char *) &debug_exec,
+ "Set whether to display execution in child process.",
+ &setlist),
+ &showlist);
add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
- (char *) &debug_events,
- "Set whether to display kernel events in child process.",
- &setlist),
- &showlist);
+ (char *) &debug_events,
+ "Set whether to display kernel events in child process.",
+ &setlist),
+ &showlist);
add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
- (char *) &debug_memory,
- "Set whether to display memory accesses in child process.",
- &setlist),
- &showlist);
+ (char *) &debug_memory,
+ "Set whether to display memory accesses in child process.",
+ &setlist),
+ &showlist);
add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
- (char *) &debug_exceptions,
- "Set whether to display kernel exceptions in child process.",
- &setlist),
- &showlist);
+ (char *) &debug_exceptions,
+ "Set whether to display kernel exceptions in child process.",
+ &setlist),
+ &showlist);
add_info ("dll", info_dll_command, "Status of loaded DLLs.");
add_info_alias ("sharedlibrary", "dll", 1);
by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
it means that the pid has died. Otherwise it is assumed to be alive. */
static int
-win32_child_thread_alive (int pid)
+win32_child_thread_alive (ptid_t ptid)
{
+ int pid = PIDGET (ptid);
+
return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
FALSE : TRUE;
}
/* Convert pid to printable format. */
char *
-cygwin_pid_to_str (int pid)
+cygwin_pid_to_str (ptid_t ptid)
{
static char buf[80];
+ int pid = PIDGET (ptid);
+
if ((DWORD) pid == current_event.dwProcessId)
sprintf (buf, "process %d", pid);
else
sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
return buf;
}
+
+static int
+core_dll_symbols_add (char *dll_name, DWORD base_addr)
+{
+ struct objfile *objfile;
+ char *objfile_basename;
+ const char *dll_basename;
+
+ if (!(dll_basename = strrchr (dll_name, '/')))
+ dll_basename = dll_name;
+ else
+ dll_basename++;
+
+ ALL_OBJFILES (objfile)
+ {
+ objfile_basename = strrchr (objfile->name, '/');
+
+ if (objfile_basename &&
+ strcmp (dll_basename, objfile_basename + 1) == 0)
+ {
+ printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
+ base_addr, dll_name);
+ goto out;
+ }
+ }
+
+ register_loaded_dll (dll_name, base_addr + 0x1000);
+ solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
+
+out:
+ return 1;
+}
+
+typedef struct
+{
+ struct target_ops *target;
+ bfd_vma addr;
+}
+map_code_section_args;
+
+static void
+map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
+{
+ int old;
+ int update_coreops;
+ struct section_table *new_target_sect_ptr;
+
+ map_code_section_args *args = (map_code_section_args *) obj;
+ struct target_ops *target = args->target;
+ if (sect->flags & SEC_CODE)
+ {
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ if (target->to_sections)
+ {
+ old = target->to_sections_end - target->to_sections;
+ target->to_sections = (struct section_table *)
+ xrealloc ((char *) target->to_sections,
+ (sizeof (struct section_table)) * (1 + old));
+ }
+ else
+ {
+ old = 0;
+ target->to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)));
+ }
+ target->to_sections_end = target->to_sections + (1 + old);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+ new_target_sect_ptr = target->to_sections + old;
+ new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
+ new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
+ bfd_section_size (abfd, sect);;
+ new_target_sect_ptr->the_bfd_section = sect;
+ new_target_sect_ptr->bfd = abfd;
+ }
+}
+
+static int
+dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
+{
+ bfd *dll_bfd;
+ map_code_section_args map_args;
+ asection *lowest_sect;
+ char *name;
+ if (dll_name == NULL || target == NULL)
+ return 0;
+ name = xstrdup (dll_name);
+ dll_bfd = bfd_openr (name, "pei-i386");
+ if (dll_bfd == NULL)
+ return 0;
+
+ if (bfd_check_format (dll_bfd, bfd_object))
+ {
+ lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
+ if (lowest_sect == NULL)
+ return 0;
+ map_args.target = target;
+ map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
+
+ bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
+ }
+
+ return 1;
+}
+
+static void
+core_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
+{
+ struct target_ops *target = (struct target_ops *) obj;
+
+ DWORD base_addr;
+
+ int dll_name_size;
+ char *dll_name = NULL;
+ char *buf = NULL;
+ struct win32_pstatus *pstatus;
+ char *p;
+
+ if (strncmp (sect->name, ".module", 7))
+ return;
+
+ buf = (char *) xmalloc (sect->_raw_size + 1);
+ if (!buf)
+ {
+ printf_unfiltered ("memory allocation failed for %s\n", sect->name);
+ goto out;
+ }
+ if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size))
+ goto out;
+
+ pstatus = (struct win32_pstatus *) buf;
+
+ memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
+ dll_name_size = pstatus->data.module_info.module_name_size;
+ if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size)
+ goto out;
+
+ dll_name = (char *) xmalloc (dll_name_size + 1);
+ if (!dll_name)
+ {
+ printf_unfiltered ("memory allocation failed for %s\n", sect->name);
+ goto out;
+ }
+ strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
+
+ while ((p = strchr (dll_name, '\\')))
+ *p = '/';
+
+ if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
+ printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
+
+ if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
+ printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
+
+out:
+ if (buf)
+ xfree (buf);
+ if (dll_name)
+ xfree (dll_name);
+ return;
+}
+
+void
+child_solib_add (char *filename ATTRIBUTE_UNUSED, int from_tty, struct target_ops *target)
+{
+ if (core_bfd)
+ {
+ child_clear_solibs ();
+ bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
+ }
+ else
+ {
+ if (solib_end && solib_end->name)
+ solib_symbols_add (solib_end->name, from_tty, solib_end->load_addr);
+ }
+}
+
+static void
+fetch_elf_core_registers (char *core_reg_sect,
+ unsigned core_reg_size,
+ int which,
+ CORE_ADDR reg_addr)
+{
+ int r;
+ if (core_reg_size < sizeof (CONTEXT))
+ {
+ error ("Core file register section too small (%u bytes).", core_reg_size);
+ return;
+ }
+ for (r = 0; r < NUM_REGS; r++)
+ supply_register (r, core_reg_sect + mappings[r]);
+}
+
+static struct core_fns win32_elf_core_fns =
+{
+ bfd_target_elf_flavour,
+ default_check_format,
+ default_core_sniffer,
+ fetch_elf_core_registers,
+ NULL
+};
+
+void
+_initialize_core_win32 (void)
+{
+ add_core_fns (&win32_elf_core_fns);
+}