/* Target-vector operations for controlling windows child processes, for GDB.
- Copyright (C) 1995-2020 Free Software Foundation, Inc.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
#include <fcntl.h>
#include <windows.h>
#include <imagehlp.h>
-#include <psapi.h>
#ifdef __CYGWIN__
#include <wchar.h>
#include <sys/cygwin.h>
#include "gdbsupport/pathstuff.h"
#include "gdbsupport/gdb_wait.h"
#include "nat/windows-nat.h"
+#include "gdbsupport/symbol.h"
using namespace windows_nat;
-#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
-#define DebugActiveProcessStop dyn_DebugActiveProcessStop
-#define DebugBreakProcess dyn_DebugBreakProcess
-#define DebugSetProcessKillOnExit dyn_DebugSetProcessKillOnExit
-#define EnumProcessModules dyn_EnumProcessModules
-#define EnumProcessModulesEx dyn_EnumProcessModulesEx
-#define GetModuleInformation dyn_GetModuleInformation
-#define LookupPrivilegeValueA dyn_LookupPrivilegeValueA
-#define OpenProcessToken dyn_OpenProcessToken
-#define GetConsoleFontSize dyn_GetConsoleFontSize
-#define GetCurrentConsoleFont dyn_GetCurrentConsoleFont
-#define Wow64SuspendThread dyn_Wow64SuspendThread
-#define Wow64GetThreadContext dyn_Wow64GetThreadContext
-#define Wow64SetThreadContext dyn_Wow64SetThreadContext
-#define Wow64GetThreadSelectorEntry dyn_Wow64GetThreadSelectorEntry
-
-typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
- PTOKEN_PRIVILEGES,
- DWORD, PTOKEN_PRIVILEGES,
- PDWORD);
-static AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
-
-typedef BOOL WINAPI (DebugActiveProcessStop_ftype) (DWORD);
-static DebugActiveProcessStop_ftype *DebugActiveProcessStop;
-
-typedef BOOL WINAPI (DebugBreakProcess_ftype) (HANDLE);
-static DebugBreakProcess_ftype *DebugBreakProcess;
-
-typedef BOOL WINAPI (DebugSetProcessKillOnExit_ftype) (BOOL);
-static DebugSetProcessKillOnExit_ftype *DebugSetProcessKillOnExit;
-
-typedef BOOL WINAPI (EnumProcessModules_ftype) (HANDLE, HMODULE *, DWORD,
- LPDWORD);
-static EnumProcessModules_ftype *EnumProcessModules;
-
-#ifdef __x86_64__
-typedef BOOL WINAPI (EnumProcessModulesEx_ftype) (HANDLE, HMODULE *, DWORD,
- LPDWORD, DWORD);
-static EnumProcessModulesEx_ftype *EnumProcessModulesEx;
-#endif
-
-typedef BOOL WINAPI (GetModuleInformation_ftype) (HANDLE, HMODULE,
- LPMODULEINFO, DWORD);
-static GetModuleInformation_ftype *GetModuleInformation;
-
-typedef BOOL WINAPI (LookupPrivilegeValueA_ftype) (LPCSTR, LPCSTR, PLUID);
-static LookupPrivilegeValueA_ftype *LookupPrivilegeValueA;
-
-typedef BOOL WINAPI (OpenProcessToken_ftype) (HANDLE, DWORD, PHANDLE);
-static OpenProcessToken_ftype *OpenProcessToken;
-
-typedef BOOL WINAPI (GetCurrentConsoleFont_ftype) (HANDLE, BOOL,
- CONSOLE_FONT_INFO *);
-static GetCurrentConsoleFont_ftype *GetCurrentConsoleFont;
-
-typedef COORD WINAPI (GetConsoleFontSize_ftype) (HANDLE, DWORD);
-static GetConsoleFontSize_ftype *GetConsoleFontSize;
-
-#ifdef __x86_64__
-typedef DWORD WINAPI (Wow64SuspendThread_ftype) (HANDLE);
-static Wow64SuspendThread_ftype *Wow64SuspendThread;
-
-typedef BOOL WINAPI (Wow64GetThreadContext_ftype) (HANDLE, PWOW64_CONTEXT);
-static Wow64GetThreadContext_ftype *Wow64GetThreadContext;
-
-typedef BOOL WINAPI (Wow64SetThreadContext_ftype) (HANDLE,
- const WOW64_CONTEXT *);
-static Wow64SetThreadContext_ftype *Wow64SetThreadContext;
-
-typedef BOOL WINAPI (Wow64GetThreadSelectorEntry_ftype) (HANDLE, DWORD,
- PLDT_ENTRY);
-static Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
-#endif
-
#undef STARTUPINFO
#undef CreateProcess
#undef GetModuleFileNameEx
#ifndef __CYGWIN__
# define __PMAX (MAX_PATH + 1)
- typedef DWORD WINAPI (GetModuleFileNameEx_ftype) (HANDLE, HMODULE, LPSTR, DWORD);
- static GetModuleFileNameEx_ftype *GetModuleFileNameEx;
+# define GetModuleFileNameEx GetModuleFileNameExA
# define STARTUPINFO STARTUPINFOA
# define CreateProcess CreateProcessA
-# define GetModuleFileNameEx_name "GetModuleFileNameExA"
-# define bad_GetModuleFileNameEx bad_GetModuleFileNameExA
#else
# define __PMAX PATH_MAX
/* The starting and ending address of the cygwin1.dll text segment. */
static CORE_ADDR cygwin_load_end;
# define __USEWIDE
typedef wchar_t cygwin_buf_t;
- typedef DWORD WINAPI (GetModuleFileNameEx_ftype) (HANDLE, HMODULE,
- LPWSTR, DWORD);
- static GetModuleFileNameEx_ftype *GetModuleFileNameEx;
+# define GetModuleFileNameEx GetModuleFileNameExW
# define STARTUPINFO STARTUPINFOW
# define CreateProcess CreateProcessW
-# define GetModuleFileNameEx_name "GetModuleFileNameExW"
-# define bad_GetModuleFileNameEx bad_GetModuleFileNameExW
#endif
static int have_saved_context; /* True if we've saved context from a
#endif
#define CONTEXT_DEBUGGER_DR CONTEXT_FULL | CONTEXT_FLOATING_POINT \
- | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS \
- | CONTEXT_EXTENDED_REGISTERS
+ | CONTEXT_SEGMENTS | CONTEXT_DEBUG_REGISTERS \
+ | CONTEXT_EXTENDED_REGISTERS
static uintptr_t dr[8];
static int debug_registers_changed;
#endif
#define CHECK(x) check (x, __FILE__,__LINE__)
-#define DEBUG_EXEC(x) if (debug_exec) debug_printf x
-#define DEBUG_EVENTS(x) if (debug_events) debug_printf x
-#define DEBUG_MEM(x) if (debug_memory) debug_printf x
-#define DEBUG_EXCEPT(x) if (debug_exceptions) debug_printf x
+#define DEBUG_EXEC(fmt, ...) \
+ debug_prefixed_printf_cond (debug_exec, "windows exec", fmt, ## __VA_ARGS__)
+#define DEBUG_EVENTS(fmt, ...) \
+ debug_prefixed_printf_cond (debug_events, "windows events", fmt, \
+ ## __VA_ARGS__)
+#define DEBUG_MEM(fmt, ...) \
+ debug_prefixed_printf_cond (debug_memory, "windows mem", fmt, \
+ ## __VA_ARGS__)
+#define DEBUG_EXCEPT(fmt, ...) \
+ debug_prefixed_printf_cond (debug_exceptions, "windows except", fmt, \
+ ## __VA_ARGS__)
static void cygwin_set_dr (int i, CORE_ADDR addr);
static void cygwin_set_dr7 (unsigned long val);
static int saw_create;
static int open_process_used = 0;
#ifdef __x86_64__
-static bool wow64_process = false;
+static void *wow64_dbgbreak;
#endif
/* User options. */
void resume (ptid_t, int , enum gdb_signal) override;
- ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+ ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
bool stopped_by_sw_breakpoint () override
{
- return current_windows_thread->stopped_at_software_breakpoint;
+ windows_thread_info *th
+ = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
+ return th->stopped_at_software_breakpoint;
}
bool supports_stopped_by_sw_breakpoint () override
const char *thread_name (struct thread_info *) override;
int get_windows_debug_event (int pid, struct target_waitstatus *ourstatus);
+
+ void do_initial_windows_stuff (DWORD pid, bool attaching);
};
static windows_nat_target the_windows_nat_target;
static void
windows_init_thread_list (void)
{
- DEBUG_EVENTS (("gdb: windows_init_thread_list\n"));
+ DEBUG_EVENTS ("called");
init_thread_list ();
for (windows_thread_info *here : thread_list)
else
{
if (th->stopped_at_software_breakpoint
+ && !th->pc_adjusted
&& r == gdbarch_pc_regnum (gdbarch))
{
int size = register_size (gdbarch, r);
value -= gdbarch_decr_pc_after_break (gdbarch);
memcpy (context_offset, &value, size);
}
+ /* Make sure we only rewrite the PC a single time. */
+ th->pc_adjusted = true;
}
regcache->raw_supply (r, context_offset);
}
{
asection *text = NULL;
- gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
+ gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386"));
if (abfd == NULL)
return so;
/* See nat/windows-nat.h. */
void
-windows_nat::handle_load_dll ()
-{
- LOAD_DLL_DEBUG_INFO *event = ¤t_event.u.LoadDll;
- const char *dll_name;
-
- /* Try getting the DLL name via the lpImageName field of the event.
- Note that Microsoft documents this fields as strictly optional,
- in the sense that it might be NULL. And the first DLL event in
- particular is explicitly documented as "likely not pass[ed]"
- (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
- dll_name = get_image_name (current_process_handle,
- event->lpImageName, event->fUnicode);
- if (!dll_name)
- return;
-
- solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
+windows_nat::handle_load_dll (const char *dll_name, LPVOID base)
+{
+ solib_end->next = windows_make_so (dll_name, base);
solib_end = solib_end->next;
lm_info_windows *li = (lm_info_windows *) solib_end->lm_info;
- DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
- host_address_to_string (li->load_addr)));
+ DEBUG_EVENTS ("Loading dll \"%s\" at %s.", solib_end->so_name,
+ host_address_to_string (li->load_addr));
}
static void
so->next = sodel->next;
if (!so->next)
solib_end = so;
- DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+ DEBUG_EVENTS ("Unloading dll \"%s\".", sodel->so_name);
windows_free_so (sodel);
return;
int
windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
{
- gdb::unique_xmalloc_ptr<char> s;
int retval = 0;
- if (!target_read_string
- ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
- &s, 1024, 0)
- || !s || !*(s.get ()))
+ gdb::unique_xmalloc_ptr<char> s
+ = (target_read_string
+ ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
+ 1024));
+ if (s == nullptr || !*(s.get ()))
/* nothing to do */;
else if (!startswith (s.get (), _CYGWIN_SIGNAL_STRING))
{
static void
display_selectors (const char * args, int from_tty)
{
- if (!current_windows_thread)
+ if (inferior_ptid == null_ptid)
{
puts_filtered ("Impossible to display selectors now.\n");
return;
}
+
+ windows_thread_info *current_windows_thread
+ = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
+
if (!args)
{
#ifdef __x86_64__
if (named_thread != NULL)
{
int thread_name_len;
- gdb::unique_xmalloc_ptr<char> thread_name;
-
- thread_name_len = target_read_string (thread_name_target,
- &thread_name, 1025, NULL);
+ gdb::unique_xmalloc_ptr<char> thread_name
+ = target_read_string (thread_name_target, 1025, &thread_name_len);
if (thread_name_len > 0)
{
thread_name.get ()[thread_name_len - 1] = '\0';
return false;
}
+/* See nat/windows-nat.h. */
+
+bool
+windows_nat::handle_access_violation (const EXCEPTION_RECORD *rec)
+{
+#ifdef __CYGWIN__
+ /* See if the access violation happened within the cygwin DLL
+ itself. Cygwin uses a kind of exception handling to deal with
+ passed-in invalid addresses. gdb should not treat these as real
+ SEGVs since they will be silently handled by cygwin. A real SEGV
+ will (theoretically) be caught by cygwin later in the process and
+ will be sent as a cygwin-specific-signal. So, ignore SEGVs if
+ they show up within the text segment of the DLL itself. */
+ const char *fn;
+ CORE_ADDR addr = (CORE_ADDR) (uintptr_t) rec->ExceptionAddress;
+
+ if ((!cygwin_exceptions && (addr >= cygwin_load_start
+ && addr < cygwin_load_end))
+ || (find_pc_partial_function (addr, &fn, NULL, NULL)
+ && startswith (fn, "KERNEL32!IsBad")))
+ return true;
+#endif
+ return false;
+}
+
/* Resume thread specified by ID, or all artificially suspended
threads, if we are continuing execution. KILLED non-zero means we
have killed the inferior, so we should ignore weird errors due to
(unsigned) GetLastError ());
/* We can not debug anything in that case. */
}
- current_windows_thread
- = windows_add_thread (ptid_t (current_event.dwProcessId,
- current_event.dwThreadId, 0),
- current_event.u.CreateThread.hThread,
- current_event.u.CreateThread.lpThreadLocalBase,
- true /* main_thread_p */);
+ windows_add_thread (ptid_t (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ current_event.u.CreateThread.hThread,
+ current_event.u.CreateThread.lpThreadLocalBase,
+ true /* main_thread_p */);
return current_event.dwThreadId;
}
{
if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
{
- DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
+ DEBUG_EXCEPT ("Cannot continue with signal %d here.", sig);
}
else if (sig == last_sig)
continue_status = DBG_EXCEPTION_NOT_HANDLED;
}
if (continue_status == DBG_CONTINUE)
{
- DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
+ DEBUG_EXCEPT ("Cannot continue with signal %d.", sig);
}
}
#endif
- DEBUG_EXCEPT(("Can only continue with received signal %d.\n",
- last_sig));
+ DEBUG_EXCEPT ("Can only continue with received signal %d.",
+ last_sig);
}
last_sig = GDB_SIGNAL_0;
- DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=0x%x, step=%d, sig=%d);\n",
- ptid.pid (), (unsigned) ptid.lwp (), step, sig));
+ DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
+ ptid.pid (), (unsigned) ptid.lwp (), step, sig);
/* Get context for currently selected thread. */
th = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
if (!new_console && !attach_flag)
return TRUE;
- if (!DebugBreakProcess (current_process_handle))
- warning (_("Could not interrupt program. "
- "Press Ctrl-c in the program console."));
+#ifdef __x86_64__
+ if (wow64_process)
+ {
+ /* Call DbgUiRemoteBreakin of the 32bit ntdll.dll in the target process.
+ DebugBreakProcess would call the one of the 64bit ntdll.dll, which
+ can't be correctly handled by gdb. */
+ if (wow64_dbgbreak == nullptr)
+ {
+ CORE_ADDR addr;
+ if (!find_minimal_symbol_address ("ntdll!DbgUiRemoteBreakin",
+ &addr, 0))
+ wow64_dbgbreak = (void *) addr;
+ }
+
+ if (wow64_dbgbreak != nullptr)
+ {
+ HANDLE thread = CreateRemoteThread (current_process_handle, NULL,
+ 0, (LPTHREAD_START_ROUTINE)
+ wow64_dbgbreak, NULL, 0, NULL);
+ if (thread)
+ CloseHandle (thread);
+ }
+ }
+ else
+#endif
+ {
+ if (!DebugBreakProcess (current_process_handle))
+ warning (_("Could not interrupt program. "
+ "Press Ctrl-c in the program console."));
+ }
/* Return true to tell that Ctrl-C has been handled. */
return TRUE;
{
BOOL debug_event;
DWORD continue_status, event_code;
- windows_thread_info *th;
- static windows_thread_info dummy_thread_info (0, 0, 0);
DWORD thread_id = 0;
/* If there is a relevant pending stop, report it now. See the
thread_id = stop->thread_id;
*ourstatus = stop->status;
- inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
- current_windows_thread = thread_rec (inferior_ptid,
- INVALIDATE_CONTEXT);
- current_windows_thread->reload_context = 1;
+ ptid_t ptid (current_event.dwProcessId, thread_id);
+ windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
+ th->reload_context = 1;
return thread_id;
}
event_code = current_event.dwDebugEventCode;
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
- th = NULL;
have_saved_context = 0;
switch (event_code)
{
case CREATE_THREAD_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "CREATE_THREAD_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "CREATE_THREAD_DEBUG_EVENT");
if (saw_create != 1)
{
inferior *inf = find_inferior_pid (this, current_event.dwProcessId);
}
/* Record the existence of this thread. */
thread_id = current_event.dwThreadId;
- th = windows_add_thread
- (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
+ windows_add_thread
+ (ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
current_event.u.CreateThread.hThread,
current_event.u.CreateThread.lpThreadLocalBase,
false /* main_thread_p */);
break;
case EXIT_THREAD_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "EXIT_THREAD_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "EXIT_THREAD_DEBUG_EVENT");
windows_delete_thread (ptid_t (current_event.dwProcessId,
current_event.dwThreadId, 0),
current_event.u.ExitThread.dwExitCode,
false /* main_thread_p */);
- th = &dummy_thread_info;
break;
case CREATE_PROCESS_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "CREATE_PROCESS_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "CREATE_PROCESS_DEBUG_EVENT");
CloseHandle (current_event.u.CreateProcessInfo.hFile);
if (++saw_create != 1)
break;
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
/* Add the main thread. */
- th = windows_add_thread
- (ptid_t (current_event.dwProcessId,
+ windows_add_thread
+ (ptid_t (current_event.dwProcessId,
current_event.dwThreadId, 0),
current_event.u.CreateProcessInfo.hThread,
current_event.u.CreateProcessInfo.lpThreadLocalBase,
break;
case EXIT_PROCESS_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "EXIT_PROCESS_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "EXIT_PROCESS_DEBUG_EVENT");
if (!windows_initialization_done)
{
target_terminal::ours ();
break;
case LOAD_DLL_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "LOAD_DLL_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "LOAD_DLL_DEBUG_EVENT");
CloseHandle (current_event.u.LoadDll.hFile);
if (saw_create != 1 || ! windows_initialization_done)
break;
- catch_errors (handle_load_dll);
+ catch_errors (dll_loaded_event);
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
thread_id = current_event.dwThreadId;
break;
case UNLOAD_DLL_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "UNLOAD_DLL_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "UNLOAD_DLL_DEBUG_EVENT");
if (saw_create != 1 || ! windows_initialization_done)
break;
catch_errors (handle_unload_dll);
break;
case EXCEPTION_DEBUG_EVENT:
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "EXCEPTION_DEBUG_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "EXCEPTION_DEBUG_EVENT");
if (saw_create != 1)
break;
switch (handle_exception (ourstatus, debug_exceptions))
break;
case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
- DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
- (unsigned) current_event.dwProcessId,
- (unsigned) current_event.dwThreadId,
- "OUTPUT_DEBUG_STRING_EVENT"));
+ DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
+ (unsigned) current_event.dwProcessId,
+ (unsigned) current_event.dwThreadId,
+ "OUTPUT_DEBUG_STRING_EVENT");
if (saw_create != 1)
break;
thread_id = handle_output_debug_string (ourstatus);
{
/* Pending stop. See the comment by the definition of
"pending_stops" for details on why this is needed. */
- DEBUG_EVENTS (("get_windows_debug_event - "
- "unexpected stop in 0x%x (expecting 0x%x)\n",
- thread_id, desired_stop_thread_id));
+ DEBUG_EVENTS ("get_windows_debug_event - "
+ "unexpected stop in 0x%x (expecting 0x%x)",
+ thread_id, desired_stop_thread_id);
if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
&& ((current_event.u.Exception.ExceptionRecord.ExceptionCode
&& windows_initialization_done)
{
ptid_t ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
- th = thread_rec (ptid, INVALIDATE_CONTEXT);
+ windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
th->stopped_at_software_breakpoint = true;
+ th->pc_adjusted = false;
}
pending_stops.push_back ({thread_id, *ourstatus, current_event});
thread_id = 0;
CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
}
- else
- {
- inferior_ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
- current_windows_thread = th;
- if (!current_windows_thread)
- current_windows_thread = thread_rec (inferior_ptid,
- INVALIDATE_CONTEXT);
- }
out:
return thread_id;
/* Wait for interesting events to occur in the target process. */
ptid_t
windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
- int options)
+ target_wait_flags options)
{
int pid = -1;
{
ptid_t result = ptid_t (current_event.dwProcessId, retval, 0);
- if (current_windows_thread != nullptr)
+ if (ourstatus->kind != TARGET_WAITKIND_EXITED
+ && ourstatus->kind != TARGET_WAITKIND_SIGNALLED)
{
- current_windows_thread->stopped_at_software_breakpoint = false;
- if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
- && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
- == EXCEPTION_BREAKPOINT)
- || (current_event.u.Exception.ExceptionRecord.ExceptionCode
- == STATUS_WX86_BREAKPOINT))
- && windows_initialization_done)
- current_windows_thread->stopped_at_software_breakpoint = true;
+ windows_thread_info *th = thread_rec (result, INVALIDATE_CONTEXT);
+
+ if (th != nullptr)
+ {
+ th->stopped_at_software_breakpoint = false;
+ if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+ && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
+ == EXCEPTION_BREAKPOINT)
+ || (current_event.u.Exception.ExceptionRecord.ExceptionCode
+ == STATUS_WX86_BREAKPOINT))
+ && windows_initialization_done)
+ {
+ th->stopped_at_software_breakpoint = true;
+ th->pc_adjusted = false;
+ }
+ }
}
return result;
}
}
-/* Iterate over all DLLs currently mapped by our inferior, and
- add them to our list of solibs. */
-
-static void
-windows_add_all_dlls (void)
-{
- HMODULE dummy_hmodule;
- DWORD cb_needed;
- HMODULE *hmodules;
- int i;
-
-#ifdef __x86_64__
- if (wow64_process)
- {
- if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
- sizeof (HMODULE), &cb_needed,
- LIST_MODULES_32BIT) == 0)
- return;
- }
- else
-#endif
- {
- if (EnumProcessModules (current_process_handle, &dummy_hmodule,
- sizeof (HMODULE), &cb_needed) == 0)
- return;
- }
-
- if (cb_needed < 1)
- return;
-
- hmodules = (HMODULE *) alloca (cb_needed);
-#ifdef __x86_64__
- if (wow64_process)
- {
- if (EnumProcessModulesEx (current_process_handle, hmodules,
- cb_needed, &cb_needed,
- LIST_MODULES_32BIT) == 0)
- return;
- }
- else
-#endif
- {
- if (EnumProcessModules (current_process_handle, hmodules,
- cb_needed, &cb_needed) == 0)
- return;
- }
-
- char system_dir[__PMAX];
- char syswow_dir[__PMAX];
- size_t system_dir_len = 0;
- bool convert_syswow_dir = false;
-#ifdef __x86_64__
- if (wow64_process)
-#endif
- {
- /* This fails on 32bit Windows because it has no SysWOW64 directory,
- and in this case a path conversion isn't necessary. */
- UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
- if (len > 0)
- {
- /* Check that we have passed a large enough buffer. */
- gdb_assert (len < sizeof (syswow_dir));
-
- len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
- /* Error check. */
- gdb_assert (len != 0);
- /* Check that we have passed a large enough buffer. */
- gdb_assert (len < sizeof (system_dir));
-
- strcat (system_dir, "\\");
- strcat (syswow_dir, "\\");
- system_dir_len = strlen (system_dir);
-
- convert_syswow_dir = true;
- }
-
- }
- for (i = 1; i < (int) (cb_needed / sizeof (HMODULE)); i++)
- {
- MODULEINFO mi;
-#ifdef __USEWIDE
- wchar_t dll_name[__PMAX];
- char dll_name_mb[__PMAX];
-#else
- char dll_name[__PMAX];
-#endif
- const char *name;
- if (GetModuleInformation (current_process_handle, hmodules[i],
- &mi, sizeof (mi)) == 0)
- continue;
- if (GetModuleFileNameEx (current_process_handle, hmodules[i],
- dll_name, sizeof (dll_name)) == 0)
- continue;
-#ifdef __USEWIDE
- wcstombs (dll_name_mb, dll_name, __PMAX);
- name = dll_name_mb;
-#else
- name = dll_name;
-#endif
- /* Convert the DLL path of 32bit processes returned by
- GetModuleFileNameEx from the 64bit system directory to the
- 32bit syswow64 directory if necessary. */
- std::string syswow_dll_path;
- if (convert_syswow_dir
- && strncasecmp (name, system_dir, system_dir_len) == 0
- && strchr (name + system_dir_len, '\\') == nullptr)
- {
- syswow_dll_path = syswow_dir;
- syswow_dll_path += name + system_dir_len;
- name = syswow_dll_path.c_str();
- }
-
- solib_end->next = windows_make_so (name, mi.lpBaseOfDll);
- solib_end = solib_end->next;
- }
-}
-
-static void
-do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
+void
+windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
{
int i;
struct inferior *inf;
#endif
current_event.dwProcessId = pid;
memset (¤t_event, 0, sizeof (current_event));
- if (!target_is_pushed (ops))
- push_target (ops);
+ inf = current_inferior ();
+ if (!inf->target_is_pushed (this))
+ inf->push_target (this);
disable_breakpoints_in_shlibs ();
windows_clear_solib ();
clear_proceed_status (0);
windows_set_segment_register_p (i386_windows_segment_register_p);
}
- inf = current_inferior ();
inferior_appeared (inf, pid);
inf->attach_flag = attaching;
- /* Make the new process the current inferior, so terminal handling
- can rely on it. When attaching, we don't know about any thread
- id here, but that's OK --- nothing should be referencing the
- current thread until we report an event out of windows_wait. */
- inferior_ptid = ptid_t (pid);
-
target_terminal::init ();
target_terminal::inferior ();
windows_initialization_done = 0;
+ ptid_t last_ptid;
+
while (1)
{
struct target_waitstatus status;
- ops->wait (minus_one_ptid, &status, 0);
+ last_ptid = this->wait (minus_one_ptid, &status, 0);
/* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread
events. */
&& status.kind != TARGET_WAITKIND_SPURIOUS)
break;
- ops->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
+ this->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
}
+ switch_to_thread (find_thread_ptid (this, last_ptid));
+
/* Now that the inferior has been started and all DLLs have been mapped,
we can iterate over all DLLs and load them in.
}
#endif
- do_initial_windows_stuff (this, pid, 1);
+ do_initial_windows_stuff (pid, 1);
target_terminal::ours ();
}
}
x86_cleanup_dregs ();
- inferior_ptid = null_ptid;
+ switch_to_no_thread ();
detach_inferior (inf);
maybe_unpush_target ();
mbstowcs (copy, env[i], len);
equalpos = wcschr (copy, L'=');
if (equalpos)
- *equalpos = L'\0';
+ *equalpos = L'\0';
SetEnvironmentVariableW (copy, NULL);
}
xfree (copy);
PROCESS_INFORMATION pi;
BOOL ret;
DWORD flags = 0;
- const char *inferior_io_terminal = get_inferior_io_terminal ();
+ const char *inferior_tty = current_inferior ()->tty ();
if (!exec_file)
error (_("No executable specified, use `target exec'."));
w32_env = NULL;
}
- if (!inferior_io_terminal)
+ if (inferior_tty == nullptr)
tty = ostdin = ostdout = ostderr = -1;
else
{
- tty = open (inferior_io_terminal, O_RDWR | O_NOCTTY);
+ tty = open (inferior_tty, O_RDWR | O_NOCTTY);
if (tty < 0)
{
- print_sys_errmsg (inferior_io_terminal, errno);
+ print_sys_errmsg (inferior_tty, errno);
ostdin = ostdout = ostderr = -1;
}
else
allargs_len = strlen (allargs_copy);
}
/* If not all the standard streams are redirected by the command
- line, use inferior_io_terminal for those which aren't. */
- if (inferior_io_terminal
+ line, use INFERIOR_TTY for those which aren't. */
+ if (inferior_tty != nullptr
&& !(fd_inp >= 0 && fd_out >= 0 && fd_err >= 0))
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = 0;
sa.bInheritHandle = TRUE;
- tty = CreateFileA (inferior_io_terminal, GENERIC_READ | GENERIC_WRITE,
+ tty = CreateFileA (inferior_tty, GENERIC_READ | GENERIC_WRITE,
0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (tty == INVALID_HANDLE_VALUE)
warning (_("Warning: Failed to open TTY %s, error %#x."),
- inferior_io_terminal, (unsigned) GetLastError ());
+ inferior_tty, (unsigned) GetLastError ());
}
if (redirected || tty != INVALID_HANDLE_VALUE)
{
else
saw_create = 0;
- do_initial_windows_stuff (this, pi.dwProcessId, 0);
+ do_initial_windows_stuff (pi.dwProcessId, 0);
/* windows_continue (DBG_CONTINUE, -1, 0); */
}
void
windows_nat_target::interrupt ()
{
- DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
+ DEBUG_EVENTS ("GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)");
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
registers_changed (); /* refresh register state */
}
if (writebuf != NULL)
{
- DEBUG_MEM (("gdb: write target memory, %s bytes at %s\n",
- pulongest (len), core_addr_to_string (memaddr)));
+ DEBUG_MEM ("write target memory, %s bytes at %s",
+ pulongest (len), core_addr_to_string (memaddr));
success = WriteProcessMemory (current_process_handle,
(LPVOID) (uintptr_t) memaddr, writebuf,
len, &done);
}
else
{
- DEBUG_MEM (("gdb: read target memory, %s bytes at %s\n",
- pulongest (len), core_addr_to_string (memaddr)));
+ DEBUG_MEM ("read target memory, %s bytes at %s",
+ pulongest (len), core_addr_to_string (memaddr));
success = ReadProcessMemory (current_process_handle,
(LPCVOID) (uintptr_t) memaddr, readbuf,
len, &done);
void
windows_nat_target::close ()
{
- DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
- inferior_ptid.pid ()));
+ DEBUG_EVENTS ("inferior_ptid=%d\n", inferior_ptid.pid ());
}
/* Convert pid to printable format. */
add_cmd ("selector", class_info, display_selectors,
_("Display selectors infos."),
&info_w32_cmdlist);
+
+ if (!initialize_loadable ())
+ {
+ /* This will probably fail on Windows 9x/Me. Let the user know
+ that we're missing some functionality. */
+ warning(_("\
+cannot automatically find executable file or library to read symbols.\n\
+Use \"file\" or \"dll\" command to load executable/libraries directly."));
+ }
}
/* Hardware watchpoint support, adapted from go32-nat.c code. */
}
}
}
-
-/* Define dummy functions which always return error for the rare cases where
- these functions could not be found. */
-static BOOL WINAPI
-bad_DebugActiveProcessStop (DWORD w)
-{
- return FALSE;
-}
-static BOOL WINAPI
-bad_DebugBreakProcess (HANDLE w)
-{
- return FALSE;
-}
-static BOOL WINAPI
-bad_DebugSetProcessKillOnExit (BOOL w)
-{
- return FALSE;
-}
-static BOOL WINAPI
-bad_EnumProcessModules (HANDLE w, HMODULE *x, DWORD y, LPDWORD z)
-{
- return FALSE;
-}
-
-#ifdef __USEWIDE
-static DWORD WINAPI
-bad_GetModuleFileNameExW (HANDLE w, HMODULE x, LPWSTR y, DWORD z)
-{
- return 0;
-}
-#else
-static DWORD WINAPI
-bad_GetModuleFileNameExA (HANDLE w, HMODULE x, LPSTR y, DWORD z)
-{
- return 0;
-}
-#endif
-
-static BOOL WINAPI
-bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
-{
- return FALSE;
-}
-
-static BOOL WINAPI
-bad_OpenProcessToken (HANDLE w, DWORD x, PHANDLE y)
-{
- return FALSE;
-}
-
-static BOOL WINAPI
-bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
-{
- f->nFont = 0;
- return 1;
-}
-static COORD WINAPI
-bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
-{
- COORD size;
- size.X = 8;
- size.Y = 12;
- return size;
-}
-
-/* Load any functions which may not be available in ancient versions
- of Windows. */
-
-void _initialize_loadable ();
-void
-_initialize_loadable ()
-{
- HMODULE hm = NULL;
-
-#define GPA(m, func) \
- func = (func ## _ftype *) GetProcAddress (m, #func)
-
- hm = LoadLibrary ("kernel32.dll");
- if (hm)
- {
- GPA (hm, DebugActiveProcessStop);
- GPA (hm, DebugBreakProcess);
- GPA (hm, DebugSetProcessKillOnExit);
- GPA (hm, GetConsoleFontSize);
- GPA (hm, DebugActiveProcessStop);
- GPA (hm, GetCurrentConsoleFont);
-#ifdef __x86_64__
- GPA (hm, Wow64SuspendThread);
- GPA (hm, Wow64GetThreadContext);
- GPA (hm, Wow64SetThreadContext);
- GPA (hm, Wow64GetThreadSelectorEntry);
-#endif
- }
-
- /* Set variables to dummy versions of these processes if the function
- wasn't found in kernel32.dll. */
- if (!DebugBreakProcess)
- DebugBreakProcess = bad_DebugBreakProcess;
- if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
- {
- DebugActiveProcessStop = bad_DebugActiveProcessStop;
- DebugSetProcessKillOnExit = bad_DebugSetProcessKillOnExit;
- }
- if (!GetConsoleFontSize)
- GetConsoleFontSize = bad_GetConsoleFontSize;
- if (!GetCurrentConsoleFont)
- GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
-
- /* Load optional functions used for retrieving filename information
- associated with the currently debugged process or its dlls. */
- hm = LoadLibrary ("psapi.dll");
- if (hm)
- {
- GPA (hm, EnumProcessModules);
-#ifdef __x86_64__
- GPA (hm, EnumProcessModulesEx);
-#endif
- GPA (hm, GetModuleInformation);
- GetModuleFileNameEx = (GetModuleFileNameEx_ftype *)
- GetProcAddress (hm, GetModuleFileNameEx_name);
- }
-
- if (!EnumProcessModules || !GetModuleInformation || !GetModuleFileNameEx)
- {
- /* Set variables to dummy versions of these processes if the function
- wasn't found in psapi.dll. */
- EnumProcessModules = bad_EnumProcessModules;
- GetModuleInformation = bad_GetModuleInformation;
- GetModuleFileNameEx = bad_GetModuleFileNameEx;
- /* This will probably fail on Windows 9x/Me. Let the user know
- that we're missing some functionality. */
- warning(_("\
-cannot automatically find executable file or library to read symbols.\n\
-Use \"file\" or \"dll\" command to load executable/libraries directly."));
- }
-
- hm = LoadLibrary ("advapi32.dll");
- if (hm)
- {
- GPA (hm, OpenProcessToken);
- GPA (hm, LookupPrivilegeValueA);
- GPA (hm, AdjustTokenPrivileges);
- /* Only need to set one of these since if OpenProcessToken fails nothing
- else is needed. */
- if (!OpenProcessToken || !LookupPrivilegeValueA
- || !AdjustTokenPrivileges)
- OpenProcessToken = bad_OpenProcessToken;
- }
-
-#undef GPA
-}