Remove some globals from nat/windows-nat.c
nat/windows-nat.c has a number of globals that it uses to communicate with its clients (gdb and gdbserver). However, if we ever want the Windows ports to be multi-inferior, globals won't work. This patch takes a step toward that by moving most nat/windows-nat.c globals into a new struct windows_process_info. Many functions are converted to be methods on this object. A couple of globals remain, as they are needed to truly be global due to the way that the Windows debugging APIs work. The clients still have a global for the current process. That is, this patch is a step toward the end goal, but doesn't implement the goal itself.
This commit is contained in:
parent
fc0b013e44
commit
0578e87f93
4 changed files with 472 additions and 420 deletions
|
@ -23,12 +23,6 @@
|
||||||
namespace windows_nat
|
namespace windows_nat
|
||||||
{
|
{
|
||||||
|
|
||||||
HANDLE current_process_handle;
|
|
||||||
DWORD current_process_id;
|
|
||||||
DWORD main_thread_id;
|
|
||||||
enum gdb_signal last_sig = GDB_SIGNAL_0;
|
|
||||||
DEBUG_EVENT current_event;
|
|
||||||
|
|
||||||
/* The most recent event from WaitForDebugEvent. Unlike
|
/* The most recent event from WaitForDebugEvent. Unlike
|
||||||
current_event, this is guaranteed never to come from a pending
|
current_event, this is guaranteed never to come from a pending
|
||||||
stop. This is important because only data from the most recent
|
stop. This is important because only data from the most recent
|
||||||
|
@ -36,15 +30,6 @@ DEBUG_EVENT current_event;
|
||||||
ContinueDebugEvent. */
|
ContinueDebugEvent. */
|
||||||
static DEBUG_EVENT last_wait_event;
|
static DEBUG_EVENT last_wait_event;
|
||||||
|
|
||||||
DWORD desired_stop_thread_id = -1;
|
|
||||||
std::vector<pending_stop> pending_stops;
|
|
||||||
EXCEPTION_RECORD siginfo_er;
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
bool wow64_process = false;
|
|
||||||
bool ignore_first_breakpoint = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
|
AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
|
||||||
DebugActiveProcessStop_ftype *DebugActiveProcessStop;
|
DebugActiveProcessStop_ftype *DebugActiveProcessStop;
|
||||||
DebugBreakProcess_ftype *DebugBreakProcess;
|
DebugBreakProcess_ftype *DebugBreakProcess;
|
||||||
|
@ -180,7 +165,8 @@ get_image_name (HANDLE h, void *address, int unicode)
|
||||||
#define MS_VC_EXCEPTION 0x406d1388
|
#define MS_VC_EXCEPTION 0x406d1388
|
||||||
|
|
||||||
handle_exception_result
|
handle_exception_result
|
||||||
handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
|
windows_process_info::handle_exception (struct target_waitstatus *ourstatus,
|
||||||
|
bool debug_exceptions)
|
||||||
{
|
{
|
||||||
#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
|
#define DEBUG_EXCEPTION_SIMPLE(x) if (debug_exceptions) \
|
||||||
debug_printf ("gdb: Target exception %s at %s\n", x, \
|
debug_printf ("gdb: Target exception %s at %s\n", x, \
|
||||||
|
@ -335,15 +321,10 @@ handle_exception (struct target_waitstatus *ourstatus, bool debug_exceptions)
|
||||||
#undef DEBUG_EXCEPTION_SIMPLE
|
#undef DEBUG_EXCEPTION_SIMPLE
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate over all DLLs currently mapped by our inferior, looking for
|
/* See nat/windows-nat.h. */
|
||||||
a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
|
|
||||||
list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
|
|
||||||
DLLs to the list of solibs; this is used when the inferior finishes
|
|
||||||
its initialization, and all the DLLs it statically depends on are
|
|
||||||
presumed loaded. */
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
windows_add_dll (LPVOID load_addr)
|
windows_process_info::add_dll (LPVOID load_addr)
|
||||||
{
|
{
|
||||||
HMODULE dummy_hmodule;
|
HMODULE dummy_hmodule;
|
||||||
DWORD cb_needed;
|
DWORD cb_needed;
|
||||||
|
@ -353,7 +334,7 @@ windows_add_dll (LPVOID load_addr)
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (wow64_process)
|
||||||
{
|
{
|
||||||
if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
|
if (EnumProcessModulesEx (handle, &dummy_hmodule,
|
||||||
sizeof (HMODULE), &cb_needed,
|
sizeof (HMODULE), &cb_needed,
|
||||||
LIST_MODULES_32BIT) == 0)
|
LIST_MODULES_32BIT) == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -361,7 +342,7 @@ windows_add_dll (LPVOID load_addr)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (EnumProcessModules (current_process_handle, &dummy_hmodule,
|
if (EnumProcessModules (handle, &dummy_hmodule,
|
||||||
sizeof (HMODULE), &cb_needed) == 0)
|
sizeof (HMODULE), &cb_needed) == 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +354,7 @@ windows_add_dll (LPVOID load_addr)
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (wow64_process)
|
||||||
{
|
{
|
||||||
if (EnumProcessModulesEx (current_process_handle, hmodules,
|
if (EnumProcessModulesEx (handle, hmodules,
|
||||||
cb_needed, &cb_needed,
|
cb_needed, &cb_needed,
|
||||||
LIST_MODULES_32BIT) == 0)
|
LIST_MODULES_32BIT) == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -381,7 +362,7 @@ windows_add_dll (LPVOID load_addr)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (EnumProcessModules (current_process_handle, hmodules,
|
if (EnumProcessModules (handle, hmodules,
|
||||||
cb_needed, &cb_needed) == 0)
|
cb_needed, &cb_needed) == 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -426,11 +407,11 @@ windows_add_dll (LPVOID load_addr)
|
||||||
char dll_name[MAX_PATH];
|
char dll_name[MAX_PATH];
|
||||||
#endif
|
#endif
|
||||||
const char *name;
|
const char *name;
|
||||||
if (GetModuleInformation (current_process_handle, hmodules[i],
|
if (GetModuleInformation (handle, hmodules[i],
|
||||||
&mi, sizeof (mi)) == 0)
|
&mi, sizeof (mi)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GetModuleFileNameEx (current_process_handle, hmodules[i],
|
if (GetModuleFileNameEx (handle, hmodules[i],
|
||||||
dll_name, sizeof (dll_name)) == 0)
|
dll_name, sizeof (dll_name)) == 0)
|
||||||
continue;
|
continue;
|
||||||
#ifdef __USEWIDE
|
#ifdef __USEWIDE
|
||||||
|
@ -466,7 +447,7 @@ windows_add_dll (LPVOID load_addr)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
dll_loaded_event ()
|
windows_process_info::dll_loaded_event ()
|
||||||
{
|
{
|
||||||
gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
|
gdb_assert (current_event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT);
|
||||||
|
|
||||||
|
@ -478,29 +459,28 @@ dll_loaded_event ()
|
||||||
in the sense that it might be NULL. And the first DLL event in
|
in the sense that it might be NULL. And the first DLL event in
|
||||||
particular is explicitly documented as "likely not pass[ed]"
|
particular is explicitly documented as "likely not pass[ed]"
|
||||||
(source: MSDN LOAD_DLL_DEBUG_INFO structure). */
|
(source: MSDN LOAD_DLL_DEBUG_INFO structure). */
|
||||||
dll_name = get_image_name (current_process_handle,
|
dll_name = get_image_name (handle, event->lpImageName, event->fUnicode);
|
||||||
event->lpImageName, event->fUnicode);
|
|
||||||
/* If the DLL name could not be gleaned via lpImageName, try harder
|
/* If the DLL name could not be gleaned via lpImageName, try harder
|
||||||
by enumerating all the DLLs loaded into the inferior, looking for
|
by enumerating all the DLLs loaded into the inferior, looking for
|
||||||
one that is loaded at base address = lpBaseOfDll. */
|
one that is loaded at base address = lpBaseOfDll. */
|
||||||
if (dll_name != nullptr)
|
if (dll_name != nullptr)
|
||||||
handle_load_dll (dll_name, event->lpBaseOfDll);
|
handle_load_dll (dll_name, event->lpBaseOfDll);
|
||||||
else if (event->lpBaseOfDll != nullptr)
|
else if (event->lpBaseOfDll != nullptr)
|
||||||
windows_add_dll (event->lpBaseOfDll);
|
add_dll (event->lpBaseOfDll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
windows_add_all_dlls ()
|
windows_process_info::add_all_dlls ()
|
||||||
{
|
{
|
||||||
windows_add_dll (nullptr);
|
add_dll (nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
matching_pending_stop (bool debug_events)
|
windows_process_info::matching_pending_stop (bool debug_events)
|
||||||
{
|
{
|
||||||
/* If there are pending stops, and we might plausibly hit one of
|
/* If there are pending stops, and we might plausibly hit one of
|
||||||
them, we don't want to actually continue the inferior -- we just
|
them, we don't want to actually continue the inferior -- we just
|
||||||
|
@ -524,7 +504,7 @@ matching_pending_stop (bool debug_events)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
gdb::optional<pending_stop>
|
gdb::optional<pending_stop>
|
||||||
fetch_pending_stop (bool debug_events)
|
windows_process_info::fetch_pending_stop (bool debug_events)
|
||||||
{
|
{
|
||||||
gdb::optional<pending_stop> result;
|
gdb::optional<pending_stop> result;
|
||||||
for (auto iter = pending_stops.begin ();
|
for (auto iter = pending_stops.begin ();
|
||||||
|
|
|
@ -109,79 +109,6 @@ enum thread_disposition_type
|
||||||
INVALIDATE_CONTEXT
|
INVALIDATE_CONTEXT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Find a thread record given a thread id. THREAD_DISPOSITION
|
|
||||||
controls whether the thread is suspended, and whether the context
|
|
||||||
is invalidated.
|
|
||||||
|
|
||||||
This function must be supplied by the embedding application. */
|
|
||||||
extern windows_thread_info *thread_rec (ptid_t ptid,
|
|
||||||
thread_disposition_type disposition);
|
|
||||||
|
|
||||||
|
|
||||||
/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. Updates
|
|
||||||
OURSTATUS and returns the thread id if this represents a thread
|
|
||||||
change (this is specific to Cygwin), otherwise 0.
|
|
||||||
|
|
||||||
Cygwin prepends its messages with a "cygwin:". Interpret this as
|
|
||||||
a Cygwin signal. Otherwise just print the string as a warning.
|
|
||||||
|
|
||||||
This function must be supplied by the embedding application. */
|
|
||||||
extern int handle_output_debug_string (struct target_waitstatus *ourstatus);
|
|
||||||
|
|
||||||
/* Handle a DLL load event.
|
|
||||||
|
|
||||||
This function assumes that the current event did not occur during
|
|
||||||
inferior initialization.
|
|
||||||
|
|
||||||
DLL_NAME is the name of the library. BASE is the base load
|
|
||||||
address.
|
|
||||||
|
|
||||||
This function must be supplied by the embedding application. */
|
|
||||||
|
|
||||||
extern void handle_load_dll (const char *dll_name, LPVOID base);
|
|
||||||
|
|
||||||
/* Handle a DLL unload event.
|
|
||||||
|
|
||||||
This function assumes that this event did not occur during inferior
|
|
||||||
initialization.
|
|
||||||
|
|
||||||
This function must be supplied by the embedding application. */
|
|
||||||
|
|
||||||
extern void handle_unload_dll ();
|
|
||||||
|
|
||||||
/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
|
|
||||||
somewhat undocumented but is used to tell the debugger the name of
|
|
||||||
a thread.
|
|
||||||
|
|
||||||
Return true if the exception was handled; return false otherwise.
|
|
||||||
|
|
||||||
This function must be supplied by the embedding application. */
|
|
||||||
|
|
||||||
extern bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
|
|
||||||
|
|
||||||
/* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding
|
|
||||||
application a chance to change it to be considered "unhandled".
|
|
||||||
This function must be supplied by the embedding application. If it
|
|
||||||
returns true, then the exception is "unhandled". */
|
|
||||||
|
|
||||||
extern bool handle_access_violation (const EXCEPTION_RECORD *rec);
|
|
||||||
|
|
||||||
|
|
||||||
/* Currently executing process */
|
|
||||||
extern HANDLE current_process_handle;
|
|
||||||
extern DWORD current_process_id;
|
|
||||||
extern DWORD main_thread_id;
|
|
||||||
extern enum gdb_signal last_sig;
|
|
||||||
|
|
||||||
/* The current debug event from WaitForDebugEvent or from a pending
|
|
||||||
stop. */
|
|
||||||
extern DEBUG_EVENT current_event;
|
|
||||||
|
|
||||||
/* The ID of the thread for which we anticipate a stop event.
|
|
||||||
Normally this is -1, meaning we'll accept an event in any
|
|
||||||
thread. */
|
|
||||||
extern DWORD desired_stop_thread_id;
|
|
||||||
|
|
||||||
/* A single pending stop. See "pending_stops" for more
|
/* A single pending stop. See "pending_stops" for more
|
||||||
information. */
|
information. */
|
||||||
struct pending_stop
|
struct pending_stop
|
||||||
|
@ -197,27 +124,6 @@ struct pending_stop
|
||||||
DEBUG_EVENT event;
|
DEBUG_EVENT event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A vector of pending stops. Sometimes, Windows will report a stop
|
|
||||||
on a thread that has been ostensibly suspended. We believe what
|
|
||||||
happens here is that two threads hit a breakpoint simultaneously,
|
|
||||||
and the Windows kernel queues the stop events. However, this can
|
|
||||||
result in the strange effect of trying to single step thread A --
|
|
||||||
leaving all other threads suspended -- and then seeing a stop in
|
|
||||||
thread B. To handle this scenario, we queue all such "pending"
|
|
||||||
stops here, and then process them once the step has completed. See
|
|
||||||
PR gdb/22992. */
|
|
||||||
extern std::vector<pending_stop> pending_stops;
|
|
||||||
|
|
||||||
/* Contents of $_siginfo */
|
|
||||||
extern EXCEPTION_RECORD siginfo_er;
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
/* The target is a WOW64 process */
|
|
||||||
extern bool wow64_process;
|
|
||||||
/* Ignore first breakpoint exception of WOW64 process */
|
|
||||||
extern bool ignore_first_breakpoint;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
HANDLE_EXCEPTION_UNHANDLED = 0,
|
HANDLE_EXCEPTION_UNHANDLED = 0,
|
||||||
|
@ -225,29 +131,140 @@ typedef enum
|
||||||
HANDLE_EXCEPTION_IGNORED
|
HANDLE_EXCEPTION_IGNORED
|
||||||
} handle_exception_result;
|
} handle_exception_result;
|
||||||
|
|
||||||
extern handle_exception_result handle_exception
|
/* A single Windows process. An object of this type (or subclass) is
|
||||||
(struct target_waitstatus *ourstatus, bool debug_exceptions);
|
created by the client. Some methods must be provided by the client
|
||||||
|
as well. */
|
||||||
|
|
||||||
/* Call to indicate that a DLL was loaded. */
|
struct windows_process_info
|
||||||
|
{
|
||||||
|
/* The process handle */
|
||||||
|
HANDLE handle = 0;
|
||||||
|
DWORD id = 0;
|
||||||
|
DWORD main_thread_id = 0;
|
||||||
|
enum gdb_signal last_sig = GDB_SIGNAL_0;
|
||||||
|
|
||||||
extern void dll_loaded_event ();
|
/* The current debug event from WaitForDebugEvent or from a pending
|
||||||
|
stop. */
|
||||||
|
DEBUG_EVENT current_event {};
|
||||||
|
|
||||||
/* Iterate over all DLLs currently mapped by our inferior, and
|
/* The ID of the thread for which we anticipate a stop event.
|
||||||
add them to our list of solibs. */
|
Normally this is -1, meaning we'll accept an event in any
|
||||||
|
thread. */
|
||||||
|
DWORD desired_stop_thread_id = -1;
|
||||||
|
|
||||||
extern void windows_add_all_dlls ();
|
/* A vector of pending stops. Sometimes, Windows will report a stop
|
||||||
|
on a thread that has been ostensibly suspended. We believe what
|
||||||
|
happens here is that two threads hit a breakpoint simultaneously,
|
||||||
|
and the Windows kernel queues the stop events. However, this can
|
||||||
|
result in the strange effect of trying to single step thread A --
|
||||||
|
leaving all other threads suspended -- and then seeing a stop in
|
||||||
|
thread B. To handle this scenario, we queue all such "pending"
|
||||||
|
stops here, and then process them once the step has completed. See
|
||||||
|
PR gdb/22992. */
|
||||||
|
std::vector<pending_stop> pending_stops;
|
||||||
|
|
||||||
/* Return true if there is a pending stop matching
|
/* Contents of $_siginfo */
|
||||||
desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
|
EXCEPTION_RECORD siginfo_er {};
|
||||||
enabled. */
|
|
||||||
|
|
||||||
extern bool matching_pending_stop (bool debug_events);
|
#ifdef __x86_64__
|
||||||
|
/* The target is a WOW64 process */
|
||||||
|
bool wow64_process = false;
|
||||||
|
/* Ignore first breakpoint exception of WOW64 process */
|
||||||
|
bool ignore_first_breakpoint = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* See if a pending stop matches DESIRED_STOP_THREAD_ID. If so,
|
|
||||||
remove it from the list of pending stops, set 'current_event', and
|
|
||||||
return it. Otherwise, return an empty optional. */
|
|
||||||
|
|
||||||
extern gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
|
/* Find a thread record given a thread id. THREAD_DISPOSITION
|
||||||
|
controls whether the thread is suspended, and whether the context
|
||||||
|
is invalidated.
|
||||||
|
|
||||||
|
This function must be supplied by the embedding application. */
|
||||||
|
windows_thread_info *thread_rec (ptid_t ptid,
|
||||||
|
thread_disposition_type disposition);
|
||||||
|
|
||||||
|
/* Handle OUTPUT_DEBUG_STRING_EVENT from child process. Updates
|
||||||
|
OURSTATUS and returns the thread id if this represents a thread
|
||||||
|
change (this is specific to Cygwin), otherwise 0.
|
||||||
|
|
||||||
|
Cygwin prepends its messages with a "cygwin:". Interpret this as
|
||||||
|
a Cygwin signal. Otherwise just print the string as a warning.
|
||||||
|
|
||||||
|
This function must be supplied by the embedding application. */
|
||||||
|
int handle_output_debug_string (struct target_waitstatus *ourstatus);
|
||||||
|
|
||||||
|
/* Handle a DLL load event.
|
||||||
|
|
||||||
|
This function assumes that the current event did not occur during
|
||||||
|
inferior initialization.
|
||||||
|
|
||||||
|
DLL_NAME is the name of the library. BASE is the base load
|
||||||
|
address.
|
||||||
|
|
||||||
|
This function must be supplied by the embedding application. */
|
||||||
|
|
||||||
|
void handle_load_dll (const char *dll_name, LPVOID base);
|
||||||
|
|
||||||
|
/* Handle a DLL unload event.
|
||||||
|
|
||||||
|
This function assumes that this event did not occur during inferior
|
||||||
|
initialization.
|
||||||
|
|
||||||
|
This function must be supplied by the embedding application. */
|
||||||
|
|
||||||
|
void handle_unload_dll ();
|
||||||
|
|
||||||
|
/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
|
||||||
|
somewhat undocumented but is used to tell the debugger the name of
|
||||||
|
a thread.
|
||||||
|
|
||||||
|
Return true if the exception was handled; return false otherwise.
|
||||||
|
|
||||||
|
This function must be supplied by the embedding application. */
|
||||||
|
|
||||||
|
bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
|
||||||
|
|
||||||
|
/* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding
|
||||||
|
application a chance to change it to be considered "unhandled".
|
||||||
|
This function must be supplied by the embedding application. If it
|
||||||
|
returns true, then the exception is "unhandled". */
|
||||||
|
|
||||||
|
bool handle_access_violation (const EXCEPTION_RECORD *rec);
|
||||||
|
|
||||||
|
handle_exception_result handle_exception
|
||||||
|
(struct target_waitstatus *ourstatus, bool debug_exceptions);
|
||||||
|
|
||||||
|
/* Call to indicate that a DLL was loaded. */
|
||||||
|
|
||||||
|
void dll_loaded_event ();
|
||||||
|
|
||||||
|
/* Iterate over all DLLs currently mapped by our inferior, and
|
||||||
|
add them to our list of solibs. */
|
||||||
|
|
||||||
|
void add_all_dlls ();
|
||||||
|
|
||||||
|
/* Return true if there is a pending stop matching
|
||||||
|
desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
|
||||||
|
enabled. */
|
||||||
|
|
||||||
|
bool matching_pending_stop (bool debug_events);
|
||||||
|
|
||||||
|
/* See if a pending stop matches DESIRED_STOP_THREAD_ID. If so,
|
||||||
|
remove it from the list of pending stops, set 'current_event', and
|
||||||
|
return it. Otherwise, return an empty optional. */
|
||||||
|
|
||||||
|
gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/* Iterate over all DLLs currently mapped by our inferior, looking for
|
||||||
|
a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
|
||||||
|
list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
|
||||||
|
DLLs to the list of solibs; this is used when the inferior finishes
|
||||||
|
its initialization, and all the DLLs it statically depends on are
|
||||||
|
presumed loaded. */
|
||||||
|
|
||||||
|
void add_dll (LPVOID load_addr);
|
||||||
|
};
|
||||||
|
|
||||||
/* A simple wrapper for ContinueDebugEvent that continues the last
|
/* A simple wrapper for ContinueDebugEvent that continues the last
|
||||||
waited-for event. If DEBUG_EVENTS is true, logging will be
|
waited-for event. If DEBUG_EVENTS is true, logging will be
|
||||||
|
|
|
@ -74,6 +74,9 @@
|
||||||
|
|
||||||
using namespace windows_nat;
|
using namespace windows_nat;
|
||||||
|
|
||||||
|
/* The current process. */
|
||||||
|
static windows_process_info windows_process;
|
||||||
|
|
||||||
#undef STARTUPINFO
|
#undef STARTUPINFO
|
||||||
#undef CreateProcess
|
#undef CreateProcess
|
||||||
#undef GetModuleFileNameEx
|
#undef GetModuleFileNameEx
|
||||||
|
@ -242,7 +245,7 @@ struct windows_nat_target final : public x86_nat_target<inf_child_target>
|
||||||
bool stopped_by_sw_breakpoint () override
|
bool stopped_by_sw_breakpoint () override
|
||||||
{
|
{
|
||||||
windows_thread_info *th
|
windows_thread_info *th
|
||||||
= thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
return th->stopped_at_software_breakpoint;
|
return th->stopped_at_software_breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +320,8 @@ check (BOOL ok, const char *file, int line)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
windows_thread_info *
|
windows_thread_info *
|
||||||
windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
|
windows_nat::windows_process_info::thread_rec
|
||||||
|
(ptid_t ptid, thread_disposition_type disposition)
|
||||||
{
|
{
|
||||||
for (auto &th : thread_list)
|
for (auto &th : thread_list)
|
||||||
if (th->tid == ptid.lwp ())
|
if (th->tid == ptid.lwp ())
|
||||||
|
@ -361,14 +365,14 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
|
||||||
|
|
||||||
gdb_assert (ptid.lwp () != 0);
|
gdb_assert (ptid.lwp () != 0);
|
||||||
|
|
||||||
if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
|
if ((th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
|
||||||
return th;
|
return th;
|
||||||
|
|
||||||
CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
|
CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
/* For WOW64 processes, this is actually the pointer to the 64bit TIB,
|
/* For WOW64 processes, this is actually the pointer to the 64bit TIB,
|
||||||
and the 32bit TIB is exactly 2 pages after it. */
|
and the 32bit TIB is exactly 2 pages after it. */
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
base += 0x2000;
|
base += 0x2000;
|
||||||
#endif
|
#endif
|
||||||
th = new windows_thread_info (ptid.lwp (), h, base);
|
th = new windows_thread_info (ptid.lwp (), h, base);
|
||||||
|
@ -462,7 +466,7 @@ windows_fetch_one_register (struct regcache *regcache,
|
||||||
|
|
||||||
char *context_ptr = (char *) &th->context;
|
char *context_ptr = (char *) &th->context;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
context_ptr = (char *) &th->wow64_context;
|
context_ptr = (char *) &th->wow64_context;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -524,7 +528,8 @@ windows_fetch_one_register (struct regcache *regcache,
|
||||||
void
|
void
|
||||||
windows_nat_target::fetch_registers (struct regcache *regcache, int r)
|
windows_nat_target::fetch_registers (struct regcache *regcache, int r)
|
||||||
{
|
{
|
||||||
windows_thread_info *th = thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
|
windows_thread_info *th
|
||||||
|
= windows_process.thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
|
||||||
|
|
||||||
/* Check if TH exists. Windows sometimes uses a non-existent
|
/* Check if TH exists. Windows sometimes uses a non-existent
|
||||||
thread id in its events. */
|
thread id in its events. */
|
||||||
|
@ -547,7 +552,7 @@ windows_nat_target::fetch_registers (struct regcache *regcache, int r)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR;
|
th->wow64_context.ContextFlags = CONTEXT_DEBUGGER_DR;
|
||||||
CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
|
CHECK (Wow64GetThreadContext (th->h, &th->wow64_context));
|
||||||
|
@ -606,7 +611,7 @@ windows_store_one_register (const struct regcache *regcache,
|
||||||
|
|
||||||
char *context_ptr = (char *) &th->context;
|
char *context_ptr = (char *) &th->context;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
context_ptr = (char *) &th->wow64_context;
|
context_ptr = (char *) &th->wow64_context;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -619,7 +624,8 @@ windows_store_one_register (const struct regcache *regcache,
|
||||||
void
|
void
|
||||||
windows_nat_target::store_registers (struct regcache *regcache, int r)
|
windows_nat_target::store_registers (struct regcache *regcache, int r)
|
||||||
{
|
{
|
||||||
windows_thread_info *th = thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
|
windows_thread_info *th
|
||||||
|
= windows_process.thread_rec (regcache->ptid (), INVALIDATE_CONTEXT);
|
||||||
|
|
||||||
/* Check if TH exists. Windows sometimes uses a non-existent
|
/* Check if TH exists. Windows sometimes uses a non-existent
|
||||||
thread id in its events. */
|
thread id in its events. */
|
||||||
|
@ -762,7 +768,8 @@ windows_make_so (const char *name, LPVOID load_addr)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
windows_nat::handle_load_dll (const char *dll_name, LPVOID base)
|
windows_nat::windows_process_info::handle_load_dll (const char *dll_name,
|
||||||
|
LPVOID base)
|
||||||
{
|
{
|
||||||
windows_solib *solib = windows_make_so (dll_name, base);
|
windows_solib *solib = windows_make_so (dll_name, base);
|
||||||
DEBUG_EVENTS ("Loading dll \"%s\" at %s.", solib->name.c_str (),
|
DEBUG_EVENTS ("Loading dll \"%s\" at %s.", solib->name.c_str (),
|
||||||
|
@ -772,7 +779,7 @@ windows_nat::handle_load_dll (const char *dll_name, LPVOID base)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
windows_nat::handle_unload_dll ()
|
windows_nat::windows_process_info::handle_unload_dll ()
|
||||||
{
|
{
|
||||||
LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
|
LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
|
||||||
|
|
||||||
|
@ -804,22 +811,6 @@ windows_nat::handle_unload_dll ()
|
||||||
host_address_to_string (lpBaseOfDll));
|
host_address_to_string (lpBaseOfDll));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call FUNC wrapped in a TRY/CATCH that swallows all GDB
|
|
||||||
exceptions. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
catch_errors (void (*func) ())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
func ();
|
|
||||||
}
|
|
||||||
catch (const gdb_exception &ex)
|
|
||||||
{
|
|
||||||
exception_print (gdb_stderr, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear list of loaded DLLs. */
|
/* Clear list of loaded DLLs. */
|
||||||
static void
|
static void
|
||||||
windows_clear_solib (void)
|
windows_clear_solib (void)
|
||||||
|
@ -849,7 +840,8 @@ signal_event_command (const char *args, int from_tty)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
int
|
int
|
||||||
windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
|
windows_nat::windows_process_info::handle_output_debug_string
|
||||||
|
(struct target_waitstatus *ourstatus)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
|
@ -914,7 +906,7 @@ display_selector (HANDLE thread, DWORD sel)
|
||||||
LDT_ENTRY info;
|
LDT_ENTRY info;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
ret = Wow64GetThreadSelectorEntry (thread, sel, &info);
|
ret = Wow64GetThreadSelectorEntry (thread, sel, &info);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -1003,12 +995,12 @@ display_selectors (const char * args, int from_tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
windows_thread_info *current_windows_thread
|
windows_thread_info *current_windows_thread
|
||||||
= thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
gdb_puts ("Selector $cs\n");
|
gdb_puts ("Selector $cs\n");
|
||||||
display_selector (current_windows_thread->h,
|
display_selector (current_windows_thread->h,
|
||||||
|
@ -1064,7 +1056,8 @@ display_selectors (const char * args, int from_tty)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
|
windows_nat::windows_process_info::handle_ms_vc_exception
|
||||||
|
(const EXCEPTION_RECORD *rec)
|
||||||
{
|
{
|
||||||
if (rec->NumberParameters >= 3
|
if (rec->NumberParameters >= 3
|
||||||
&& (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000)
|
&& (rec->ExceptionInformation[0] & 0xffffffff) == 0x1000)
|
||||||
|
@ -1103,7 +1096,8 @@ windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
windows_nat::handle_access_violation (const EXCEPTION_RECORD *rec)
|
windows_nat::windows_process_info::handle_access_violation
|
||||||
|
(const EXCEPTION_RECORD *rec)
|
||||||
{
|
{
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
/* See if the access violation happened within the cygwin DLL
|
/* See if the access violation happened within the cygwin DLL
|
||||||
|
@ -1134,16 +1128,16 @@ windows_continue (DWORD continue_status, int id, int killed)
|
||||||
{
|
{
|
||||||
BOOL res;
|
BOOL res;
|
||||||
|
|
||||||
desired_stop_thread_id = id;
|
windows_process.desired_stop_thread_id = id;
|
||||||
|
|
||||||
if (matching_pending_stop (debug_events))
|
if (windows_process.matching_pending_stop (debug_events))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
for (auto &th : thread_list)
|
for (auto &th : thread_list)
|
||||||
if (id == -1 || id == (int) th->tid)
|
if (id == -1 || id == (int) th->tid)
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
if (th->debug_registers_changed)
|
if (th->debug_registers_changed)
|
||||||
{
|
{
|
||||||
|
@ -1225,9 +1219,10 @@ windows_continue (DWORD continue_status, int id, int killed)
|
||||||
static DWORD
|
static DWORD
|
||||||
fake_create_process (void)
|
fake_create_process (void)
|
||||||
{
|
{
|
||||||
current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
|
windows_process.handle
|
||||||
current_event.dwProcessId);
|
= OpenProcess (PROCESS_ALL_ACCESS, FALSE,
|
||||||
if (current_process_handle != NULL)
|
windows_process.current_event.dwProcessId);
|
||||||
|
if (windows_process.handle != NULL)
|
||||||
open_process_used = 1;
|
open_process_used = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1235,12 +1230,12 @@ fake_create_process (void)
|
||||||
(unsigned) GetLastError ());
|
(unsigned) GetLastError ());
|
||||||
/* We can not debug anything in that case. */
|
/* We can not debug anything in that case. */
|
||||||
}
|
}
|
||||||
windows_add_thread (ptid_t (current_event.dwProcessId, 0,
|
windows_add_thread (ptid_t (windows_process.current_event.dwProcessId, 0,
|
||||||
current_event.dwThreadId),
|
windows_process.current_event.dwThreadId),
|
||||||
current_event.u.CreateThread.hThread,
|
windows_process.current_event.u.CreateThread.hThread,
|
||||||
current_event.u.CreateThread.lpThreadLocalBase,
|
windows_process.current_event.u.CreateThread.lpThreadLocalBase,
|
||||||
true /* main_thread_p */);
|
true /* main_thread_p */);
|
||||||
return current_event.dwThreadId;
|
return windows_process.current_event.dwThreadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1259,11 +1254,12 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
|
||||||
|
|
||||||
if (sig != GDB_SIGNAL_0)
|
if (sig != GDB_SIGNAL_0)
|
||||||
{
|
{
|
||||||
if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
|
if (windows_process.current_event.dwDebugEventCode
|
||||||
|
!= EXCEPTION_DEBUG_EVENT)
|
||||||
{
|
{
|
||||||
DEBUG_EXCEPT ("Cannot continue with signal %d here.", sig);
|
DEBUG_EXCEPT ("Cannot continue with signal %d here.", sig);
|
||||||
}
|
}
|
||||||
else if (sig == last_sig)
|
else if (sig == windows_process.last_sig)
|
||||||
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
else
|
else
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1287,20 +1283,20 @@ windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DEBUG_EXCEPT ("Can only continue with received signal %d.",
|
DEBUG_EXCEPT ("Can only continue with received signal %d.",
|
||||||
last_sig);
|
windows_process.last_sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
|
|
||||||
DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
|
DEBUG_EXEC ("pid=%d, tid=0x%x, step=%d, sig=%d",
|
||||||
ptid.pid (), (unsigned) ptid.lwp (), step, sig);
|
ptid.pid (), (unsigned) ptid.lwp (), step, sig);
|
||||||
|
|
||||||
/* Get context for currently selected thread. */
|
/* Get context for currently selected thread. */
|
||||||
th = thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
th = windows_process.thread_rec (inferior_ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
if (th)
|
if (th)
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
if (step)
|
if (step)
|
||||||
{
|
{
|
||||||
|
@ -1385,7 +1381,7 @@ ctrl_c_handler (DWORD event_type)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
/* Call DbgUiRemoteBreakin of the 32bit ntdll.dll in the target process.
|
/* Call DbgUiRemoteBreakin of the 32bit ntdll.dll in the target process.
|
||||||
DebugBreakProcess would call the one of the 64bit ntdll.dll, which
|
DebugBreakProcess would call the one of the 64bit ntdll.dll, which
|
||||||
|
@ -1400,7 +1396,7 @@ ctrl_c_handler (DWORD event_type)
|
||||||
|
|
||||||
if (wow64_dbgbreak != nullptr)
|
if (wow64_dbgbreak != nullptr)
|
||||||
{
|
{
|
||||||
HANDLE thread = CreateRemoteThread (current_process_handle, NULL,
|
HANDLE thread = CreateRemoteThread (windows_process.handle, NULL,
|
||||||
0, (LPTHREAD_START_ROUTINE)
|
0, (LPTHREAD_START_ROUTINE)
|
||||||
wow64_dbgbreak, NULL, 0, NULL);
|
wow64_dbgbreak, NULL, 0, NULL);
|
||||||
if (thread)
|
if (thread)
|
||||||
|
@ -1410,7 +1406,7 @@ ctrl_c_handler (DWORD event_type)
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!DebugBreakProcess (current_process_handle))
|
if (!DebugBreakProcess (windows_process.handle))
|
||||||
warning (_("Could not interrupt program. "
|
warning (_("Could not interrupt program. "
|
||||||
"Press Ctrl-c in the program console."));
|
"Press Ctrl-c in the program console."));
|
||||||
}
|
}
|
||||||
|
@ -1433,27 +1429,31 @@ windows_nat_target::get_windows_debug_event (int pid,
|
||||||
/* If there is a relevant pending stop, report it now. See the
|
/* If there is a relevant pending stop, report it now. See the
|
||||||
comment by the definition of "pending_stops" for details on why
|
comment by the definition of "pending_stops" for details on why
|
||||||
this is needed. */
|
this is needed. */
|
||||||
gdb::optional<pending_stop> stop = fetch_pending_stop (debug_events);
|
gdb::optional<pending_stop> stop
|
||||||
|
= windows_process.fetch_pending_stop (debug_events);
|
||||||
if (stop.has_value ())
|
if (stop.has_value ())
|
||||||
{
|
{
|
||||||
thread_id = stop->thread_id;
|
thread_id = stop->thread_id;
|
||||||
*ourstatus = stop->status;
|
*ourstatus = stop->status;
|
||||||
|
|
||||||
ptid_t ptid (current_event.dwProcessId, thread_id);
|
ptid_t ptid (windows_process.current_event.dwProcessId, thread_id);
|
||||||
windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
|
windows_thread_info *th
|
||||||
|
= windows_process.thread_rec (ptid, INVALIDATE_CONTEXT);
|
||||||
th->reload_context = true;
|
th->reload_context = true;
|
||||||
|
|
||||||
return thread_id;
|
return thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
|
DEBUG_EVENT *current_event = &windows_process.current_event;
|
||||||
|
|
||||||
if (!(debug_event = wait_for_debug_event (¤t_event, 1000)))
|
if (!(debug_event = wait_for_debug_event (&windows_process.current_event,
|
||||||
|
1000)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
continue_status = DBG_CONTINUE;
|
continue_status = DBG_CONTINUE;
|
||||||
|
|
||||||
event_code = current_event.dwDebugEventCode;
|
event_code = windows_process.current_event.dwDebugEventCode;
|
||||||
ourstatus->set_spurious ();
|
ourstatus->set_spurious ();
|
||||||
have_saved_context = 0;
|
have_saved_context = 0;
|
||||||
|
|
||||||
|
@ -1461,12 +1461,12 @@ windows_nat_target::get_windows_debug_event (int pid,
|
||||||
{
|
{
|
||||||
case CREATE_THREAD_DEBUG_EVENT:
|
case CREATE_THREAD_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"CREATE_THREAD_DEBUG_EVENT");
|
"CREATE_THREAD_DEBUG_EVENT");
|
||||||
if (saw_create != 1)
|
if (saw_create != 1)
|
||||||
{
|
{
|
||||||
inferior *inf = find_inferior_pid (this, current_event.dwProcessId);
|
inferior *inf = find_inferior_pid (this, current_event->dwProcessId);
|
||||||
if (!saw_create && inf->attach_flag)
|
if (!saw_create && inf->attach_flag)
|
||||||
{
|
{
|
||||||
/* Kludge around a Windows bug where first event is a create
|
/* Kludge around a Windows bug where first event is a create
|
||||||
|
@ -1479,64 +1479,64 @@ windows_nat_target::get_windows_debug_event (int pid,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Record the existence of this thread. */
|
/* Record the existence of this thread. */
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
windows_add_thread
|
windows_add_thread
|
||||||
(ptid_t (current_event.dwProcessId, current_event.dwThreadId, 0),
|
(ptid_t (current_event->dwProcessId, current_event->dwThreadId, 0),
|
||||||
current_event.u.CreateThread.hThread,
|
current_event->u.CreateThread.hThread,
|
||||||
current_event.u.CreateThread.lpThreadLocalBase,
|
current_event->u.CreateThread.lpThreadLocalBase,
|
||||||
false /* main_thread_p */);
|
false /* main_thread_p */);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_THREAD_DEBUG_EVENT:
|
case EXIT_THREAD_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"EXIT_THREAD_DEBUG_EVENT");
|
"EXIT_THREAD_DEBUG_EVENT");
|
||||||
windows_delete_thread (ptid_t (current_event.dwProcessId,
|
windows_delete_thread (ptid_t (current_event->dwProcessId,
|
||||||
current_event.dwThreadId, 0),
|
current_event->dwThreadId, 0),
|
||||||
current_event.u.ExitThread.dwExitCode,
|
current_event->u.ExitThread.dwExitCode,
|
||||||
false /* main_thread_p */);
|
false /* main_thread_p */);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"CREATE_PROCESS_DEBUG_EVENT");
|
"CREATE_PROCESS_DEBUG_EVENT");
|
||||||
CloseHandle (current_event.u.CreateProcessInfo.hFile);
|
CloseHandle (current_event->u.CreateProcessInfo.hFile);
|
||||||
if (++saw_create != 1)
|
if (++saw_create != 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
|
windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
|
||||||
/* Add the main thread. */
|
/* Add the main thread. */
|
||||||
windows_add_thread
|
windows_add_thread
|
||||||
(ptid_t (current_event.dwProcessId,
|
(ptid_t (current_event->dwProcessId,
|
||||||
current_event.dwThreadId, 0),
|
current_event->dwThreadId, 0),
|
||||||
current_event.u.CreateProcessInfo.hThread,
|
current_event->u.CreateProcessInfo.hThread,
|
||||||
current_event.u.CreateProcessInfo.lpThreadLocalBase,
|
current_event->u.CreateProcessInfo.lpThreadLocalBase,
|
||||||
true /* main_thread_p */);
|
true /* main_thread_p */);
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"EXIT_PROCESS_DEBUG_EVENT");
|
"EXIT_PROCESS_DEBUG_EVENT");
|
||||||
if (!windows_initialization_done)
|
if (!windows_initialization_done)
|
||||||
{
|
{
|
||||||
target_terminal::ours ();
|
target_terminal::ours ();
|
||||||
target_mourn_inferior (inferior_ptid);
|
target_mourn_inferior (inferior_ptid);
|
||||||
error (_("During startup program exited with code 0x%x."),
|
error (_("During startup program exited with code 0x%x."),
|
||||||
(unsigned int) current_event.u.ExitProcess.dwExitCode);
|
(unsigned int) current_event->u.ExitProcess.dwExitCode);
|
||||||
}
|
}
|
||||||
else if (saw_create == 1)
|
else if (saw_create == 1)
|
||||||
{
|
{
|
||||||
windows_delete_thread (ptid_t (current_event.dwProcessId,
|
windows_delete_thread (ptid_t (current_event->dwProcessId,
|
||||||
current_event.dwThreadId, 0),
|
current_event->dwThreadId, 0),
|
||||||
0, true /* main_thread_p */);
|
0, true /* main_thread_p */);
|
||||||
DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
|
DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
|
||||||
/* If the exit status looks like a fatal exception, but we
|
/* If the exit status looks like a fatal exception, but we
|
||||||
don't recognize the exception's code, make the original
|
don't recognize the exception's code, make the original
|
||||||
exit status value available, to avoid losing
|
exit status value available, to avoid losing
|
||||||
|
@ -1548,50 +1548,64 @@ windows_nat_target::get_windows_debug_event (int pid,
|
||||||
else
|
else
|
||||||
ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
|
ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
|
||||||
|
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOAD_DLL_DEBUG_EVENT:
|
case LOAD_DLL_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"LOAD_DLL_DEBUG_EVENT");
|
"LOAD_DLL_DEBUG_EVENT");
|
||||||
CloseHandle (current_event.u.LoadDll.hFile);
|
CloseHandle (current_event->u.LoadDll.hFile);
|
||||||
if (saw_create != 1 || ! windows_initialization_done)
|
if (saw_create != 1 || ! windows_initialization_done)
|
||||||
break;
|
break;
|
||||||
catch_errors (dll_loaded_event);
|
try
|
||||||
|
{
|
||||||
|
windows_process.dll_loaded_event ();
|
||||||
|
}
|
||||||
|
catch (const gdb_exception &ex)
|
||||||
|
{
|
||||||
|
exception_print (gdb_stderr, ex);
|
||||||
|
}
|
||||||
ourstatus->set_loaded ();
|
ourstatus->set_loaded ();
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNLOAD_DLL_DEBUG_EVENT:
|
case UNLOAD_DLL_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"UNLOAD_DLL_DEBUG_EVENT");
|
"UNLOAD_DLL_DEBUG_EVENT");
|
||||||
if (saw_create != 1 || ! windows_initialization_done)
|
if (saw_create != 1 || ! windows_initialization_done)
|
||||||
break;
|
break;
|
||||||
catch_errors (handle_unload_dll);
|
try
|
||||||
|
{
|
||||||
|
windows_process.handle_unload_dll ();
|
||||||
|
}
|
||||||
|
catch (const gdb_exception &ex)
|
||||||
|
{
|
||||||
|
exception_print (gdb_stderr, ex);
|
||||||
|
}
|
||||||
ourstatus->set_loaded ();
|
ourstatus->set_loaded ();
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXCEPTION_DEBUG_EVENT:
|
case EXCEPTION_DEBUG_EVENT:
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"EXCEPTION_DEBUG_EVENT");
|
"EXCEPTION_DEBUG_EVENT");
|
||||||
if (saw_create != 1)
|
if (saw_create != 1)
|
||||||
break;
|
break;
|
||||||
switch (handle_exception (ourstatus, debug_exceptions))
|
switch (windows_process.handle_exception (ourstatus, debug_exceptions))
|
||||||
{
|
{
|
||||||
case HANDLE_EXCEPTION_UNHANDLED:
|
case HANDLE_EXCEPTION_UNHANDLED:
|
||||||
default:
|
default:
|
||||||
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
break;
|
break;
|
||||||
case HANDLE_EXCEPTION_HANDLED:
|
case HANDLE_EXCEPTION_HANDLED:
|
||||||
thread_id = current_event.dwThreadId;
|
thread_id = current_event->dwThreadId;
|
||||||
break;
|
break;
|
||||||
case HANDLE_EXCEPTION_IGNORED:
|
case HANDLE_EXCEPTION_IGNORED:
|
||||||
continue_status = DBG_CONTINUE;
|
continue_status = DBG_CONTINUE;
|
||||||
|
@ -1601,52 +1615,57 @@ windows_nat_target::get_windows_debug_event (int pid,
|
||||||
|
|
||||||
case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
|
case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
|
||||||
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
DEBUG_EVENTS ("kernel event for pid=%u tid=0x%x code=%s",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
"OUTPUT_DEBUG_STRING_EVENT");
|
"OUTPUT_DEBUG_STRING_EVENT");
|
||||||
if (saw_create != 1)
|
if (saw_create != 1)
|
||||||
break;
|
break;
|
||||||
thread_id = handle_output_debug_string (ourstatus);
|
thread_id = windows_process.handle_output_debug_string (ourstatus);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (saw_create != 1)
|
if (saw_create != 1)
|
||||||
break;
|
break;
|
||||||
gdb_printf ("gdb: kernel event for pid=%u tid=0x%x\n",
|
gdb_printf ("gdb: kernel event for pid=%u tid=0x%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId);
|
(unsigned) current_event->dwThreadId);
|
||||||
gdb_printf (" unknown event code %u\n",
|
gdb_printf (" unknown event code %u\n",
|
||||||
(unsigned) current_event.dwDebugEventCode);
|
(unsigned) current_event->dwDebugEventCode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!thread_id || saw_create != 1)
|
if (!thread_id || saw_create != 1)
|
||||||
{
|
{
|
||||||
CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
|
CHECK (windows_continue (continue_status,
|
||||||
|
windows_process.desired_stop_thread_id, 0));
|
||||||
}
|
}
|
||||||
else if (desired_stop_thread_id != -1 && desired_stop_thread_id != thread_id)
|
else if (windows_process.desired_stop_thread_id != -1
|
||||||
|
&& windows_process.desired_stop_thread_id != thread_id)
|
||||||
{
|
{
|
||||||
/* Pending stop. See the comment by the definition of
|
/* Pending stop. See the comment by the definition of
|
||||||
"pending_stops" for details on why this is needed. */
|
"pending_stops" for details on why this is needed. */
|
||||||
DEBUG_EVENTS ("get_windows_debug_event - "
|
DEBUG_EVENTS ("get_windows_debug_event - "
|
||||||
"unexpected stop in 0x%x (expecting 0x%x)",
|
"unexpected stop in 0x%x (expecting 0x%x)",
|
||||||
thread_id, desired_stop_thread_id);
|
thread_id, windows_process.desired_stop_thread_id);
|
||||||
|
|
||||||
if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
|
if (current_event->dwDebugEventCode == EXCEPTION_DEBUG_EVENT
|
||||||
&& ((current_event.u.Exception.ExceptionRecord.ExceptionCode
|
&& ((current_event->u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== EXCEPTION_BREAKPOINT)
|
== EXCEPTION_BREAKPOINT)
|
||||||
|| (current_event.u.Exception.ExceptionRecord.ExceptionCode
|
|| (current_event->u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== STATUS_WX86_BREAKPOINT))
|
== STATUS_WX86_BREAKPOINT))
|
||||||
&& windows_initialization_done)
|
&& windows_initialization_done)
|
||||||
{
|
{
|
||||||
ptid_t ptid = ptid_t (current_event.dwProcessId, thread_id, 0);
|
ptid_t ptid = ptid_t (current_event->dwProcessId, thread_id, 0);
|
||||||
windows_thread_info *th = thread_rec (ptid, INVALIDATE_CONTEXT);
|
windows_thread_info *th
|
||||||
|
= windows_process.thread_rec (ptid, INVALIDATE_CONTEXT);
|
||||||
th->stopped_at_software_breakpoint = true;
|
th->stopped_at_software_breakpoint = true;
|
||||||
th->pc_adjusted = false;
|
th->pc_adjusted = false;
|
||||||
}
|
}
|
||||||
pending_stops.push_back ({thread_id, *ourstatus, current_event});
|
windows_process.pending_stops.push_back
|
||||||
|
({thread_id, *ourstatus, windows_process.current_event});
|
||||||
thread_id = 0;
|
thread_id = 0;
|
||||||
CHECK (windows_continue (continue_status, desired_stop_thread_id, 0));
|
CHECK (windows_continue (continue_status,
|
||||||
|
windows_process.desired_stop_thread_id, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -1702,20 +1721,23 @@ windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||||
|
|
||||||
if (retval)
|
if (retval)
|
||||||
{
|
{
|
||||||
ptid_t result = ptid_t (current_event.dwProcessId, retval, 0);
|
ptid_t result = ptid_t (windows_process.current_event.dwProcessId,
|
||||||
|
retval, 0);
|
||||||
|
|
||||||
if (ourstatus->kind () != TARGET_WAITKIND_EXITED
|
if (ourstatus->kind () != TARGET_WAITKIND_EXITED
|
||||||
&& ourstatus->kind () != TARGET_WAITKIND_SIGNALLED)
|
&& ourstatus->kind () != TARGET_WAITKIND_SIGNALLED)
|
||||||
{
|
{
|
||||||
windows_thread_info *th = thread_rec (result, INVALIDATE_CONTEXT);
|
windows_thread_info *th
|
||||||
|
= windows_process.thread_rec (result, INVALIDATE_CONTEXT);
|
||||||
|
|
||||||
if (th != nullptr)
|
if (th != nullptr)
|
||||||
{
|
{
|
||||||
th->stopped_at_software_breakpoint = false;
|
th->stopped_at_software_breakpoint = false;
|
||||||
if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
|
if (windows_process.current_event.dwDebugEventCode
|
||||||
&& ((current_event.u.Exception.ExceptionRecord.ExceptionCode
|
== EXCEPTION_DEBUG_EVENT
|
||||||
|
&& ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== EXCEPTION_BREAKPOINT)
|
== EXCEPTION_BREAKPOINT)
|
||||||
|| (current_event.u.Exception.ExceptionRecord.ExceptionCode
|
|| (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== STATUS_WX86_BREAKPOINT))
|
== STATUS_WX86_BREAKPOINT))
|
||||||
&& windows_initialization_done)
|
&& windows_initialization_done)
|
||||||
{
|
{
|
||||||
|
@ -1746,15 +1768,16 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
|
||||||
int i;
|
int i;
|
||||||
struct inferior *inf;
|
struct inferior *inf;
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
open_process_used = 0;
|
open_process_used = 0;
|
||||||
for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
|
for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
|
||||||
dr[i] = 0;
|
dr[i] = 0;
|
||||||
#ifdef __CYGWIN__
|
#ifdef __CYGWIN__
|
||||||
cygwin_load_start = cygwin_load_end = 0;
|
cygwin_load_start = cygwin_load_end = 0;
|
||||||
#endif
|
#endif
|
||||||
current_event.dwProcessId = pid;
|
windows_process.current_event.dwProcessId = pid;
|
||||||
memset (¤t_event, 0, sizeof (current_event));
|
memset (&windows_process.current_event, 0,
|
||||||
|
sizeof (windows_process.current_event));
|
||||||
inf = current_inferior ();
|
inf = current_inferior ();
|
||||||
if (!inf->target_is_pushed (this))
|
if (!inf->target_is_pushed (this))
|
||||||
inf->push_target (this);
|
inf->push_target (this);
|
||||||
|
@ -1764,9 +1787,10 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
|
||||||
init_wait_for_inferior ();
|
init_wait_for_inferior ();
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
ignore_first_breakpoint = !attaching && wow64_process;
|
windows_process.ignore_first_breakpoint
|
||||||
|
= !attaching && windows_process.wow64_process;
|
||||||
|
|
||||||
if (!wow64_process)
|
if (!windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
windows_set_context_register_offsets (amd64_mappings);
|
windows_set_context_register_offsets (amd64_mappings);
|
||||||
windows_set_segment_register_p (amd64_windows_segment_register_p);
|
windows_set_segment_register_p (amd64_windows_segment_register_p);
|
||||||
|
@ -1820,7 +1844,7 @@ windows_nat_target::do_initial_windows_stuff (DWORD pid, bool attaching)
|
||||||
Rather than try to work around this sort of issue, it is much
|
Rather than try to work around this sort of issue, it is much
|
||||||
simpler to just ignore DLL load/unload events during the startup
|
simpler to just ignore DLL load/unload events during the startup
|
||||||
phase, and then process them all in one batch now. */
|
phase, and then process them all in one batch now. */
|
||||||
windows_add_all_dlls ();
|
windows_process.add_all_dlls ();
|
||||||
|
|
||||||
windows_initialization_done = 1;
|
windows_initialization_done = 1;
|
||||||
return;
|
return;
|
||||||
|
@ -1918,7 +1942,7 @@ windows_nat_target::attach (const char *args, int from_tty)
|
||||||
{
|
{
|
||||||
BOOL wow64;
|
BOOL wow64;
|
||||||
if (IsWow64Process (h, &wow64))
|
if (IsWow64Process (h, &wow64))
|
||||||
wow64_process = wow64;
|
windows_process.wow64_process = wow64;
|
||||||
CloseHandle (h);
|
CloseHandle (h);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1935,10 +1959,11 @@ windows_nat_target::detach (inferior *inf, int from_tty)
|
||||||
ptid_t ptid = minus_one_ptid;
|
ptid_t ptid = minus_one_ptid;
|
||||||
resume (ptid, 0, GDB_SIGNAL_0);
|
resume (ptid, 0, GDB_SIGNAL_0);
|
||||||
|
|
||||||
if (!DebugActiveProcessStop (current_event.dwProcessId))
|
if (!DebugActiveProcessStop (windows_process.current_event.dwProcessId))
|
||||||
{
|
{
|
||||||
error (_("Can't detach process %u (error %u)"),
|
error (_("Can't detach process %u (error %u)"),
|
||||||
(unsigned) current_event.dwProcessId, (unsigned) GetLastError ());
|
(unsigned) windows_process.current_event.dwProcessId,
|
||||||
|
(unsigned) GetLastError ());
|
||||||
detached = 0;
|
detached = 0;
|
||||||
}
|
}
|
||||||
DebugSetProcessKillOnExit (FALSE);
|
DebugSetProcessKillOnExit (FALSE);
|
||||||
|
@ -1972,18 +1997,20 @@ windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
|
||||||
|
|
||||||
cbNeeded = 0;
|
cbNeeded = 0;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
if (!EnumProcessModulesEx (current_process_handle, &dh_buf,
|
if (!EnumProcessModulesEx (windows_process.handle,
|
||||||
sizeof (HMODULE), &cbNeeded,
|
&dh_buf, sizeof (HMODULE), &cbNeeded,
|
||||||
LIST_MODULES_32BIT) || !cbNeeded)
|
LIST_MODULES_32BIT)
|
||||||
|
|| !cbNeeded)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!EnumProcessModules (current_process_handle, &dh_buf,
|
if (!EnumProcessModules (windows_process.handle,
|
||||||
sizeof (HMODULE), &cbNeeded) || !cbNeeded)
|
&dh_buf, sizeof (HMODULE), &cbNeeded)
|
||||||
|
|| !cbNeeded)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2007,7 +2034,7 @@ windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
|
||||||
error (_("Error converting executable filename to POSIX: %d."), errno);
|
error (_("Error converting executable filename to POSIX: %d."), errno);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
len = GetModuleFileNameEx (current_process_handle,
|
len = GetModuleFileNameEx (windows_process.handle,
|
||||||
dh_buf, exe_name_ret, exe_name_max_len);
|
dh_buf, exe_name_ret, exe_name_max_len);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
error (_("Error getting executable filename: %u."),
|
error (_("Error getting executable filename: %u."),
|
||||||
|
@ -2748,7 +2775,7 @@ windows_nat_target::create_inferior (const char *exec_file,
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
BOOL wow64;
|
BOOL wow64;
|
||||||
if (IsWow64Process (pi.hProcess, &wow64))
|
if (IsWow64Process (pi.hProcess, &wow64))
|
||||||
wow64_process = wow64;
|
windows_process.wow64_process = wow64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CloseHandle (pi.hThread);
|
CloseHandle (pi.hThread);
|
||||||
|
@ -2771,10 +2798,10 @@ windows_nat_target::mourn_inferior ()
|
||||||
x86_cleanup_dregs();
|
x86_cleanup_dregs();
|
||||||
if (open_process_used)
|
if (open_process_used)
|
||||||
{
|
{
|
||||||
CHECK (CloseHandle (current_process_handle));
|
CHECK (CloseHandle (windows_process.handle));
|
||||||
open_process_used = 0;
|
open_process_used = 0;
|
||||||
}
|
}
|
||||||
siginfo_er.ExceptionCode = 0;
|
windows_process.siginfo_er.ExceptionCode = 0;
|
||||||
inf_child_target::mourn_inferior ();
|
inf_child_target::mourn_inferior ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2785,7 +2812,8 @@ void
|
||||||
windows_nat_target::interrupt ()
|
windows_nat_target::interrupt ()
|
||||||
{
|
{
|
||||||
DEBUG_EVENTS ("GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)");
|
DEBUG_EVENTS ("GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)");
|
||||||
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
|
CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT,
|
||||||
|
windows_process.current_event.dwProcessId));
|
||||||
registers_changed (); /* refresh register state */
|
registers_changed (); /* refresh register state */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2804,19 +2832,19 @@ windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
|
||||||
{
|
{
|
||||||
DEBUG_MEM ("write target memory, %s bytes at %s",
|
DEBUG_MEM ("write target memory, %s bytes at %s",
|
||||||
pulongest (len), core_addr_to_string (memaddr));
|
pulongest (len), core_addr_to_string (memaddr));
|
||||||
success = WriteProcessMemory (current_process_handle,
|
success = WriteProcessMemory (windows_process.handle,
|
||||||
(LPVOID) (uintptr_t) memaddr, writebuf,
|
(LPVOID) (uintptr_t) memaddr, writebuf,
|
||||||
len, &done);
|
len, &done);
|
||||||
if (!success)
|
if (!success)
|
||||||
lasterror = GetLastError ();
|
lasterror = GetLastError ();
|
||||||
FlushInstructionCache (current_process_handle,
|
FlushInstructionCache (windows_process.handle,
|
||||||
(LPCVOID) (uintptr_t) memaddr, len);
|
(LPCVOID) (uintptr_t) memaddr, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUG_MEM ("read target memory, %s bytes at %s",
|
DEBUG_MEM ("read target memory, %s bytes at %s",
|
||||||
pulongest (len), core_addr_to_string (memaddr));
|
pulongest (len), core_addr_to_string (memaddr));
|
||||||
success = ReadProcessMemory (current_process_handle,
|
success = ReadProcessMemory (windows_process.handle,
|
||||||
(LPCVOID) (uintptr_t) memaddr, readbuf,
|
(LPCVOID) (uintptr_t) memaddr, readbuf,
|
||||||
len, &done);
|
len, &done);
|
||||||
if (!success)
|
if (!success)
|
||||||
|
@ -2832,15 +2860,16 @@ windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
|
||||||
void
|
void
|
||||||
windows_nat_target::kill ()
|
windows_nat_target::kill ()
|
||||||
{
|
{
|
||||||
CHECK (TerminateProcess (current_process_handle, 0));
|
CHECK (TerminateProcess (windows_process.handle, 0));
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!windows_continue (DBG_CONTINUE, -1, 1))
|
if (!windows_continue (DBG_CONTINUE, -1, 1))
|
||||||
break;
|
break;
|
||||||
if (!wait_for_debug_event (¤t_event, INFINITE))
|
if (!wait_for_debug_event (&windows_process.current_event, INFINITE))
|
||||||
break;
|
break;
|
||||||
if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
|
if (windows_process.current_event.dwDebugEventCode
|
||||||
|
== EXIT_PROCESS_DEBUG_EVENT)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2906,28 +2935,31 @@ static enum target_xfer_status
|
||||||
windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
|
windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
|
||||||
ULONGEST *xfered_len)
|
ULONGEST *xfered_len)
|
||||||
{
|
{
|
||||||
char *buf = (char *) &siginfo_er;
|
char *buf = (char *) &windows_process.siginfo_er;
|
||||||
size_t bufsize = sizeof (siginfo_er);
|
size_t bufsize = sizeof (windows_process.siginfo_er);
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
EXCEPTION_RECORD32 er32;
|
EXCEPTION_RECORD32 er32;
|
||||||
if (wow64_process)
|
if (windows_process.wow64_process)
|
||||||
{
|
{
|
||||||
buf = (char *) &er32;
|
buf = (char *) &er32;
|
||||||
bufsize = sizeof (er32);
|
bufsize = sizeof (er32);
|
||||||
|
|
||||||
er32.ExceptionCode = siginfo_er.ExceptionCode;
|
er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
|
||||||
er32.ExceptionFlags = siginfo_er.ExceptionFlags;
|
er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
|
||||||
er32.ExceptionRecord = (uintptr_t) siginfo_er.ExceptionRecord;
|
er32.ExceptionRecord
|
||||||
er32.ExceptionAddress = (uintptr_t) siginfo_er.ExceptionAddress;
|
= (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
|
||||||
er32.NumberParameters = siginfo_er.NumberParameters;
|
er32.ExceptionAddress
|
||||||
|
= (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
|
||||||
|
er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
|
for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
|
||||||
er32.ExceptionInformation[i] = siginfo_er.ExceptionInformation[i];
|
er32.ExceptionInformation[i]
|
||||||
|
= windows_process.siginfo_er.ExceptionInformation[i];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (siginfo_er.ExceptionCode == 0)
|
if (windows_process.siginfo_er.ExceptionCode == 0)
|
||||||
return TARGET_XFER_E_IO;
|
return TARGET_XFER_E_IO;
|
||||||
|
|
||||||
if (readbuf == nullptr)
|
if (readbuf == nullptr)
|
||||||
|
@ -2985,7 +3017,7 @@ windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
|
||||||
{
|
{
|
||||||
windows_thread_info *th;
|
windows_thread_info *th;
|
||||||
|
|
||||||
th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
if (th == NULL)
|
if (th == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -3006,7 +3038,8 @@ windows_nat_target::get_ada_task_ptid (long lwp, ULONGEST thread)
|
||||||
const char *
|
const char *
|
||||||
windows_nat_target::thread_name (struct thread_info *thr)
|
windows_nat_target::thread_name (struct thread_info *thr)
|
||||||
{
|
{
|
||||||
return thread_rec (thr->ptid, DONT_INVALIDATE_CONTEXT)->name.get ();
|
return windows_process.thread_rec (thr->ptid,
|
||||||
|
DONT_INVALIDATE_CONTEXT)->name.get ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3178,8 +3211,9 @@ windows_nat_target::thread_alive (ptid_t ptid)
|
||||||
{
|
{
|
||||||
gdb_assert (ptid.lwp () != 0);
|
gdb_assert (ptid.lwp () != 0);
|
||||||
|
|
||||||
return (WaitForSingleObject (thread_rec (ptid, DONT_INVALIDATE_CONTEXT)->h, 0)
|
windows_thread_info *th
|
||||||
!= WAIT_OBJECT_0);
|
= windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
|
return WaitForSingleObject (th->h, 0) != WAIT_OBJECT_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initialize_check_for_gdb_ini ();
|
void _initialize_check_for_gdb_ini ();
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
using namespace windows_nat;
|
using namespace windows_nat;
|
||||||
|
|
||||||
|
static windows_process_info windows_process;
|
||||||
|
|
||||||
#ifndef USE_WIN32API
|
#ifndef USE_WIN32API
|
||||||
#include <sys/cygwin.h>
|
#include <sys/cygwin.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -163,7 +165,8 @@ win32_require_context (windows_thread_info *th)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
windows_thread_info *
|
windows_thread_info *
|
||||||
windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
|
windows_nat::windows_process_info::thread_rec
|
||||||
|
(ptid_t ptid, thread_disposition_type disposition)
|
||||||
{
|
{
|
||||||
thread_info *thread = find_thread_ptid (ptid);
|
thread_info *thread = find_thread_ptid (ptid);
|
||||||
if (thread == NULL)
|
if (thread == NULL)
|
||||||
|
@ -182,7 +185,7 @@ child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
|
||||||
windows_thread_info *th;
|
windows_thread_info *th;
|
||||||
ptid_t ptid = ptid_t (pid, tid, 0);
|
ptid_t ptid = ptid_t (pid, tid, 0);
|
||||||
|
|
||||||
if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
|
if ((th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
|
||||||
return th;
|
return th;
|
||||||
|
|
||||||
CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
|
CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
|
||||||
|
@ -295,15 +298,15 @@ child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
|
||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
{
|
{
|
||||||
success = WriteProcessMemory (current_process_handle, (LPVOID) addr,
|
success = WriteProcessMemory (windows_process.handle, (LPVOID) addr,
|
||||||
(LPCVOID) our, len, &done);
|
(LPCVOID) our, len, &done);
|
||||||
if (!success)
|
if (!success)
|
||||||
lasterror = GetLastError ();
|
lasterror = GetLastError ();
|
||||||
FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
|
FlushInstructionCache (windows_process.handle, (LPCVOID) addr, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = ReadProcessMemory (current_process_handle, (LPCVOID) addr,
|
success = ReadProcessMemory (windows_process.handle, (LPCVOID) addr,
|
||||||
(LPVOID) our, len, &done);
|
(LPVOID) our, len, &done);
|
||||||
if (!success)
|
if (!success)
|
||||||
lasterror = GetLastError ();
|
lasterror = GetLastError ();
|
||||||
|
@ -331,17 +334,17 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
|
||||||
{
|
{
|
||||||
struct process_info *proc;
|
struct process_info *proc;
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
|
windows_process.handle = proch;
|
||||||
current_process_handle = proch;
|
windows_process.id = pid;
|
||||||
current_process_id = pid;
|
windows_process.main_thread_id = 0;
|
||||||
main_thread_id = 0;
|
|
||||||
|
|
||||||
soft_interrupt_requested = 0;
|
soft_interrupt_requested = 0;
|
||||||
faked_breakpoint = 0;
|
faked_breakpoint = 0;
|
||||||
open_process_used = true;
|
open_process_used = true;
|
||||||
|
|
||||||
memset (¤t_event, 0, sizeof (current_event));
|
memset (&windows_process.current_event, 0,
|
||||||
|
sizeof (windows_process.current_event));
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
BOOL wow64;
|
BOOL wow64;
|
||||||
|
@ -417,7 +420,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
|
||||||
Rather than try to work around this sort of issue, it is much
|
Rather than try to work around this sort of issue, it is much
|
||||||
simpler to just ignore DLL load/unload events during the startup
|
simpler to just ignore DLL load/unload events during the startup
|
||||||
phase, and then process them all in one batch now. */
|
phase, and then process them all in one batch now. */
|
||||||
windows_add_all_dlls ();
|
windows_process.add_all_dlls ();
|
||||||
|
|
||||||
child_initialization_done = 1;
|
child_initialization_done = 1;
|
||||||
}
|
}
|
||||||
|
@ -456,8 +459,8 @@ continue_one_thread (thread_info *thread, int thread_id)
|
||||||
static BOOL
|
static BOOL
|
||||||
child_continue (DWORD continue_status, int thread_id)
|
child_continue (DWORD continue_status, int thread_id)
|
||||||
{
|
{
|
||||||
desired_stop_thread_id = thread_id;
|
windows_process.desired_stop_thread_id = thread_id;
|
||||||
if (matching_pending_stop (debug_threads))
|
if (windows_process.matching_pending_stop (debug_threads))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* The inferior will only continue after the ContinueDebugEvent
|
/* The inferior will only continue after the ContinueDebugEvent
|
||||||
|
@ -476,8 +479,9 @@ static void
|
||||||
child_fetch_inferior_registers (struct regcache *regcache, int r)
|
child_fetch_inferior_registers (struct regcache *regcache, int r)
|
||||||
{
|
{
|
||||||
int regno;
|
int regno;
|
||||||
windows_thread_info *th = thread_rec (current_thread_ptid (),
|
windows_thread_info *th
|
||||||
INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (current_thread_ptid (),
|
||||||
|
INVALIDATE_CONTEXT);
|
||||||
if (r == -1 || r > NUM_REGS)
|
if (r == -1 || r > NUM_REGS)
|
||||||
child_fetch_inferior_registers (regcache, NUM_REGS);
|
child_fetch_inferior_registers (regcache, NUM_REGS);
|
||||||
else
|
else
|
||||||
|
@ -491,8 +495,9 @@ static void
|
||||||
child_store_inferior_registers (struct regcache *regcache, int r)
|
child_store_inferior_registers (struct regcache *regcache, int r)
|
||||||
{
|
{
|
||||||
int regno;
|
int regno;
|
||||||
windows_thread_info *th = thread_rec (current_thread_ptid (),
|
windows_thread_info *th
|
||||||
INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (current_thread_ptid (),
|
||||||
|
INVALIDATE_CONTEXT);
|
||||||
if (r == -1 || r == 0 || r > NUM_REGS)
|
if (r == -1 || r == 0 || r > NUM_REGS)
|
||||||
child_store_inferior_registers (regcache, NUM_REGS);
|
child_store_inferior_registers (regcache, NUM_REGS);
|
||||||
else
|
else
|
||||||
|
@ -671,12 +676,12 @@ win32_process_target::create_inferior (const char *program,
|
||||||
|
|
||||||
/* Wait till we are at 1st instruction in program, return new pid
|
/* Wait till we are at 1st instruction in program, return new pid
|
||||||
(assuming success). */
|
(assuming success). */
|
||||||
cs.last_ptid = wait (ptid_t (current_process_id), &cs.last_status, 0);
|
cs.last_ptid = wait (ptid_t (windows_process.id), &cs.last_status, 0);
|
||||||
|
|
||||||
/* Necessary for handle_v_kill. */
|
/* Necessary for handle_v_kill. */
|
||||||
signal_pid = current_process_id;
|
signal_pid = windows_process.id;
|
||||||
|
|
||||||
return current_process_id;
|
return windows_process.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach to a running process.
|
/* Attach to a running process.
|
||||||
|
@ -712,7 +717,8 @@ win32_process_target::attach (unsigned long pid)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
int
|
int
|
||||||
windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
|
windows_nat::windows_process_info::handle_output_debug_string
|
||||||
|
(struct target_waitstatus *ourstatus)
|
||||||
{
|
{
|
||||||
#define READ_BUFFER_LEN 1024
|
#define READ_BUFFER_LEN 1024
|
||||||
CORE_ADDR addr;
|
CORE_ADDR addr;
|
||||||
|
@ -762,12 +768,12 @@ win32_clear_inferiors (void)
|
||||||
{
|
{
|
||||||
if (open_process_used)
|
if (open_process_used)
|
||||||
{
|
{
|
||||||
CloseHandle (current_process_handle);
|
CloseHandle (windows_process.handle);
|
||||||
open_process_used = false;
|
open_process_used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_thread (delete_thread_info);
|
for_each_thread (delete_thread_info);
|
||||||
siginfo_er.ExceptionCode = 0;
|
windows_process.siginfo_er.ExceptionCode = 0;
|
||||||
clear_inferiors ();
|
clear_inferiors ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,17 +782,19 @@ win32_clear_inferiors (void)
|
||||||
int
|
int
|
||||||
win32_process_target::kill (process_info *process)
|
win32_process_target::kill (process_info *process)
|
||||||
{
|
{
|
||||||
TerminateProcess (current_process_handle, 0);
|
TerminateProcess (windows_process.handle, 0);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (!child_continue (DBG_CONTINUE, -1))
|
if (!child_continue (DBG_CONTINUE, -1))
|
||||||
break;
|
break;
|
||||||
if (!wait_for_debug_event (¤t_event, INFINITE))
|
if (!wait_for_debug_event (&windows_process.current_event, INFINITE))
|
||||||
break;
|
break;
|
||||||
if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
|
if (windows_process.current_event.dwDebugEventCode
|
||||||
|
== EXIT_PROCESS_DEBUG_EVENT)
|
||||||
break;
|
break;
|
||||||
else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
|
else if (windows_process.current_event.dwDebugEventCode
|
||||||
handle_output_debug_string (nullptr);
|
== OUTPUT_DEBUG_STRING_EVENT)
|
||||||
|
windows_process.handle_output_debug_string (nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
win32_clear_inferiors ();
|
win32_clear_inferiors ();
|
||||||
|
@ -806,7 +814,7 @@ win32_process_target::detach (process_info *process)
|
||||||
resume.sig = 0;
|
resume.sig = 0;
|
||||||
this->resume (&resume, 1);
|
this->resume (&resume, 1);
|
||||||
|
|
||||||
if (!DebugActiveProcessStop (current_process_id))
|
if (!DebugActiveProcessStop (windows_process.id))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DebugSetProcessKillOnExit (FALSE);
|
DebugSetProcessKillOnExit (FALSE);
|
||||||
|
@ -866,7 +874,7 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
|
||||||
else
|
else
|
||||||
/* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
|
/* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make
|
||||||
the Windows resume code do the right thing for thread switching. */
|
the Windows resume code do the right thing for thread switching. */
|
||||||
tid = current_event.dwThreadId;
|
tid = windows_process.current_event.dwThreadId;
|
||||||
|
|
||||||
if (resume_info[0].thread != minus_one_ptid)
|
if (resume_info[0].thread != minus_one_ptid)
|
||||||
{
|
{
|
||||||
|
@ -881,23 +889,24 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
|
||||||
|
|
||||||
if (sig != GDB_SIGNAL_0)
|
if (sig != GDB_SIGNAL_0)
|
||||||
{
|
{
|
||||||
if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
|
if (windows_process.current_event.dwDebugEventCode
|
||||||
|
!= EXCEPTION_DEBUG_EVENT)
|
||||||
{
|
{
|
||||||
OUTMSG (("Cannot continue with signal %s here.\n",
|
OUTMSG (("Cannot continue with signal %s here.\n",
|
||||||
gdb_signal_to_string (sig)));
|
gdb_signal_to_string (sig)));
|
||||||
}
|
}
|
||||||
else if (sig == last_sig)
|
else if (sig == windows_process.last_sig)
|
||||||
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
else
|
else
|
||||||
OUTMSG (("Can only continue with received signal %s.\n",
|
OUTMSG (("Can only continue with received signal %s.\n",
|
||||||
gdb_signal_to_string (last_sig)));
|
gdb_signal_to_string (windows_process.last_sig)));
|
||||||
}
|
}
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
|
|
||||||
/* Get context for the currently selected thread. */
|
/* Get context for the currently selected thread. */
|
||||||
ptid = debug_event_ptid (¤t_event);
|
ptid = debug_event_ptid (&windows_process.current_event);
|
||||||
th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
if (th)
|
if (th)
|
||||||
{
|
{
|
||||||
win32_prepare_to_resume (th);
|
win32_prepare_to_resume (th);
|
||||||
|
@ -938,7 +947,8 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
windows_nat::handle_load_dll (const char *name, LPVOID base)
|
windows_nat::windows_process_info::handle_load_dll (const char *name,
|
||||||
|
LPVOID base)
|
||||||
{
|
{
|
||||||
CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
|
CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
|
||||||
|
|
||||||
|
@ -992,7 +1002,7 @@ windows_nat::handle_load_dll (const char *name, LPVOID base)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
void
|
void
|
||||||
windows_nat::handle_unload_dll ()
|
windows_nat::windows_process_info::handle_unload_dll ()
|
||||||
{
|
{
|
||||||
CORE_ADDR load_addr =
|
CORE_ADDR load_addr =
|
||||||
(CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
|
(CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
|
||||||
|
@ -1019,10 +1029,11 @@ fake_breakpoint_event (void)
|
||||||
|
|
||||||
faked_breakpoint = 1;
|
faked_breakpoint = 1;
|
||||||
|
|
||||||
memset (¤t_event, 0, sizeof (current_event));
|
memset (&windows_process.current_event, 0,
|
||||||
current_event.dwThreadId = main_thread_id;
|
sizeof (windows_process.current_event));
|
||||||
current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
|
windows_process.current_event.dwThreadId = windows_process.main_thread_id;
|
||||||
current_event.u.Exception.ExceptionRecord.ExceptionCode
|
windows_process.current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
|
||||||
|
windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
|
||||||
= EXCEPTION_BREAKPOINT;
|
= EXCEPTION_BREAKPOINT;
|
||||||
|
|
||||||
for_each_thread (suspend_one_thread);
|
for_each_thread (suspend_one_thread);
|
||||||
|
@ -1031,7 +1042,8 @@ fake_breakpoint_event (void)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
|
windows_nat::windows_process_info::handle_ms_vc_exception
|
||||||
|
(const EXCEPTION_RECORD *rec)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1039,7 +1051,8 @@ windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
|
||||||
/* See nat/windows-nat.h. */
|
/* See nat/windows-nat.h. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
windows_nat::handle_access_violation (const EXCEPTION_RECORD *rec)
|
windows_nat::windows_process_info::handle_access_violation
|
||||||
|
(const EXCEPTION_RECORD *rec)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1054,14 +1067,15 @@ maybe_adjust_pc ()
|
||||||
struct regcache *regcache = get_thread_regcache (current_thread, 1);
|
struct regcache *regcache = get_thread_regcache (current_thread, 1);
|
||||||
child_fetch_inferior_registers (regcache, -1);
|
child_fetch_inferior_registers (regcache, -1);
|
||||||
|
|
||||||
windows_thread_info *th = thread_rec (current_thread_ptid (),
|
windows_thread_info *th
|
||||||
DONT_INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (current_thread_ptid (),
|
||||||
|
DONT_INVALIDATE_CONTEXT);
|
||||||
th->stopped_at_software_breakpoint = false;
|
th->stopped_at_software_breakpoint = false;
|
||||||
|
|
||||||
if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
|
if (windows_process.current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
|
||||||
&& ((current_event.u.Exception.ExceptionRecord.ExceptionCode
|
&& ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== EXCEPTION_BREAKPOINT)
|
== EXCEPTION_BREAKPOINT)
|
||||||
|| (current_event.u.Exception.ExceptionRecord.ExceptionCode
|
|| (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
|
||||||
== STATUS_WX86_BREAKPOINT))
|
== STATUS_WX86_BREAKPOINT))
|
||||||
&& child_initialization_done)
|
&& child_initialization_done)
|
||||||
{
|
{
|
||||||
|
@ -1080,13 +1094,15 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
{
|
{
|
||||||
ptid_t ptid;
|
ptid_t ptid;
|
||||||
|
|
||||||
last_sig = GDB_SIGNAL_0;
|
windows_process.last_sig = GDB_SIGNAL_0;
|
||||||
ourstatus->set_spurious ();
|
ourstatus->set_spurious ();
|
||||||
*continue_status = DBG_CONTINUE;
|
*continue_status = DBG_CONTINUE;
|
||||||
|
|
||||||
/* Check if GDB sent us an interrupt request. */
|
/* Check if GDB sent us an interrupt request. */
|
||||||
check_remote_input_interrupt_request ();
|
check_remote_input_interrupt_request ();
|
||||||
|
|
||||||
|
DEBUG_EVENT *current_event = &windows_process.current_event;
|
||||||
|
|
||||||
if (soft_interrupt_requested)
|
if (soft_interrupt_requested)
|
||||||
{
|
{
|
||||||
soft_interrupt_requested = 0;
|
soft_interrupt_requested = 0;
|
||||||
|
@ -1096,12 +1112,13 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
|
|
||||||
attaching = 0;
|
attaching = 0;
|
||||||
{
|
{
|
||||||
gdb::optional<pending_stop> stop = fetch_pending_stop (debug_threads);
|
gdb::optional<pending_stop> stop
|
||||||
|
= windows_process.fetch_pending_stop (debug_threads);
|
||||||
if (stop.has_value ())
|
if (stop.has_value ())
|
||||||
{
|
{
|
||||||
*ourstatus = stop->status;
|
*ourstatus = stop->status;
|
||||||
current_event = stop->event;
|
windows_process.current_event = stop->event;
|
||||||
ptid = debug_event_ptid (¤t_event);
|
ptid = debug_event_ptid (&windows_process.current_event);
|
||||||
switch_to_thread (find_thread_ptid (ptid));
|
switch_to_thread (find_thread_ptid (ptid));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1109,7 +1126,7 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
/* Keep the wait time low enough for comfortable remote
|
/* Keep the wait time low enough for comfortable remote
|
||||||
interruption, but high enough so gdbserver doesn't become a
|
interruption, but high enough so gdbserver doesn't become a
|
||||||
bottleneck. */
|
bottleneck. */
|
||||||
if (!wait_for_debug_event (¤t_event, 250))
|
if (!wait_for_debug_event (&windows_process.current_event, 250))
|
||||||
{
|
{
|
||||||
DWORD e = GetLastError();
|
DWORD e = GetLastError();
|
||||||
|
|
||||||
|
@ -1129,28 +1146,28 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
|
|
||||||
gotevent:
|
gotevent:
|
||||||
|
|
||||||
switch (current_event.dwDebugEventCode)
|
switch (current_event->dwDebugEventCode)
|
||||||
{
|
{
|
||||||
case CREATE_THREAD_DEBUG_EVENT:
|
case CREATE_THREAD_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x)\n",
|
"for pid=%u tid=%x)\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
|
|
||||||
/* Record the existence of this thread. */
|
/* Record the existence of this thread. */
|
||||||
child_add_thread (current_event.dwProcessId,
|
child_add_thread (current_event->dwProcessId,
|
||||||
current_event.dwThreadId,
|
current_event->dwThreadId,
|
||||||
current_event.u.CreateThread.hThread,
|
current_event->u.CreateThread.hThread,
|
||||||
current_event.u.CreateThread.lpThreadLocalBase);
|
current_event->u.CreateThread.lpThreadLocalBase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_THREAD_DEBUG_EVENT:
|
case EXIT_THREAD_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
child_delete_thread (current_event.dwProcessId,
|
child_delete_thread (current_event->dwProcessId,
|
||||||
current_event.dwThreadId);
|
current_event->dwThreadId);
|
||||||
|
|
||||||
switch_to_thread (get_first_thread ());
|
switch_to_thread (get_first_thread ());
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1158,33 +1175,33 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
CloseHandle (current_event.u.CreateProcessInfo.hFile);
|
CloseHandle (current_event->u.CreateProcessInfo.hFile);
|
||||||
|
|
||||||
if (open_process_used)
|
if (open_process_used)
|
||||||
{
|
{
|
||||||
CloseHandle (current_process_handle);
|
CloseHandle (windows_process.handle);
|
||||||
open_process_used = false;
|
open_process_used = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
|
windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
|
||||||
main_thread_id = current_event.dwThreadId;
|
windows_process.main_thread_id = current_event->dwThreadId;
|
||||||
|
|
||||||
/* Add the main thread. */
|
/* Add the main thread. */
|
||||||
child_add_thread (current_event.dwProcessId,
|
child_add_thread (current_event->dwProcessId,
|
||||||
main_thread_id,
|
windows_process.main_thread_id,
|
||||||
current_event.u.CreateProcessInfo.hThread,
|
current_event->u.CreateProcessInfo.hThread,
|
||||||
current_event.u.CreateProcessInfo.lpThreadLocalBase);
|
current_event->u.CreateProcessInfo.lpThreadLocalBase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIT_PROCESS_DEBUG_EVENT:
|
case EXIT_PROCESS_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
{
|
{
|
||||||
DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
|
DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
|
||||||
/* If the exit status looks like a fatal exception, but we
|
/* If the exit status looks like a fatal exception, but we
|
||||||
don't recognize the exception's code, make the original
|
don't recognize the exception's code, make the original
|
||||||
exit status value available, to avoid losing information. */
|
exit status value available, to avoid losing information. */
|
||||||
|
@ -1195,18 +1212,18 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
else
|
else
|
||||||
ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
|
ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
|
||||||
}
|
}
|
||||||
child_continue (DBG_CONTINUE, desired_stop_thread_id);
|
child_continue (DBG_CONTINUE, windows_process.desired_stop_thread_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOAD_DLL_DEBUG_EVENT:
|
case LOAD_DLL_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
CloseHandle (current_event.u.LoadDll.hFile);
|
CloseHandle (current_event->u.LoadDll.hFile);
|
||||||
if (! child_initialization_done)
|
if (! child_initialization_done)
|
||||||
break;
|
break;
|
||||||
dll_loaded_event ();
|
windows_process.dll_loaded_event ();
|
||||||
|
|
||||||
ourstatus->set_loaded ();
|
ourstatus->set_loaded ();
|
||||||
break;
|
break;
|
||||||
|
@ -1214,20 +1231,20 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
case UNLOAD_DLL_DEBUG_EVENT:
|
case UNLOAD_DLL_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
if (! child_initialization_done)
|
if (! child_initialization_done)
|
||||||
break;
|
break;
|
||||||
handle_unload_dll ();
|
windows_process.handle_unload_dll ();
|
||||||
ourstatus->set_loaded ();
|
ourstatus->set_loaded ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXCEPTION_DEBUG_EVENT:
|
case EXCEPTION_DEBUG_EVENT:
|
||||||
OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
|
OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
if (handle_exception (ourstatus, debug_threads)
|
if (windows_process.handle_exception (ourstatus, debug_threads)
|
||||||
== HANDLE_EXCEPTION_UNHANDLED)
|
== HANDLE_EXCEPTION_UNHANDLED)
|
||||||
*continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
*continue_status = DBG_EXCEPTION_NOT_HANDLED;
|
||||||
break;
|
break;
|
||||||
|
@ -1236,31 +1253,33 @@ get_child_debug_event (DWORD *continue_status,
|
||||||
/* A message from the kernel (or Cygwin). */
|
/* A message from the kernel (or Cygwin). */
|
||||||
OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
|
OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
|
||||||
"for pid=%u tid=%x\n",
|
"for pid=%u tid=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId));
|
(unsigned) current_event->dwThreadId));
|
||||||
handle_output_debug_string (nullptr);
|
windows_process.handle_output_debug_string (nullptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
OUTMSG2 (("gdbserver: kernel event unknown "
|
OUTMSG2 (("gdbserver: kernel event unknown "
|
||||||
"for pid=%u tid=%x code=%x\n",
|
"for pid=%u tid=%x code=%x\n",
|
||||||
(unsigned) current_event.dwProcessId,
|
(unsigned) current_event->dwProcessId,
|
||||||
(unsigned) current_event.dwThreadId,
|
(unsigned) current_event->dwThreadId,
|
||||||
(unsigned) current_event.dwDebugEventCode));
|
(unsigned) current_event->dwDebugEventCode));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptid = debug_event_ptid (¤t_event);
|
ptid = debug_event_ptid (&windows_process.current_event);
|
||||||
|
|
||||||
if (desired_stop_thread_id != -1 && desired_stop_thread_id != ptid.lwp ())
|
if (windows_process.desired_stop_thread_id != -1
|
||||||
|
&& windows_process.desired_stop_thread_id != ptid.lwp ())
|
||||||
{
|
{
|
||||||
/* Pending stop. See the comment by the definition of
|
/* Pending stop. See the comment by the definition of
|
||||||
"pending_stops" for details on why this is needed. */
|
"pending_stops" for details on why this is needed. */
|
||||||
OUTMSG2 (("get_windows_debug_event - "
|
OUTMSG2 (("get_windows_debug_event - "
|
||||||
"unexpected stop in 0x%lx (expecting 0x%x)\n",
|
"unexpected stop in 0x%lx (expecting 0x%x)\n",
|
||||||
ptid.lwp (), desired_stop_thread_id));
|
ptid.lwp (), windows_process.desired_stop_thread_id));
|
||||||
maybe_adjust_pc ();
|
maybe_adjust_pc ();
|
||||||
pending_stops.push_back ({(DWORD) ptid.lwp (), *ourstatus, current_event});
|
windows_process.pending_stops.push_back
|
||||||
|
({(DWORD) ptid.lwp (), *ourstatus, *current_event});
|
||||||
ourstatus->set_spurious ();
|
ourstatus->set_spurious ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1284,7 +1303,7 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
||||||
fails). Report it now. */
|
fails). Report it now. */
|
||||||
*ourstatus = cached_status;
|
*ourstatus = cached_status;
|
||||||
cached_status.set_ignore ();
|
cached_status.set_ignore ();
|
||||||
return debug_event_ptid (¤t_event);
|
return debug_event_ptid (&windows_process.current_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -1299,7 +1318,7 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
||||||
OUTMSG2 (("Child exited with retcode = %x\n",
|
OUTMSG2 (("Child exited with retcode = %x\n",
|
||||||
ourstatus->exit_status ()));
|
ourstatus->exit_status ()));
|
||||||
win32_clear_inferiors ();
|
win32_clear_inferiors ();
|
||||||
return ptid_t (current_event.dwProcessId);
|
return ptid_t (windows_process.current_event.dwProcessId);
|
||||||
case TARGET_WAITKIND_STOPPED:
|
case TARGET_WAITKIND_STOPPED:
|
||||||
case TARGET_WAITKIND_SIGNALLED:
|
case TARGET_WAITKIND_SIGNALLED:
|
||||||
case TARGET_WAITKIND_LOADED:
|
case TARGET_WAITKIND_LOADED:
|
||||||
|
@ -1307,7 +1326,7 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
||||||
OUTMSG2 (("Child Stopped with signal = %d \n",
|
OUTMSG2 (("Child Stopped with signal = %d \n",
|
||||||
ourstatus->sig ()));
|
ourstatus->sig ()));
|
||||||
maybe_adjust_pc ();
|
maybe_adjust_pc ();
|
||||||
return debug_event_ptid (¤t_event);
|
return debug_event_ptid (&windows_process.current_event);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
OUTMSG (("Ignoring unknown internal event, %d\n",
|
OUTMSG (("Ignoring unknown internal event, %d\n",
|
||||||
|
@ -1315,7 +1334,8 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case TARGET_WAITKIND_SPURIOUS:
|
case TARGET_WAITKIND_SPURIOUS:
|
||||||
/* do nothing, just continue */
|
/* do nothing, just continue */
|
||||||
child_continue (continue_status, desired_stop_thread_id);
|
child_continue (continue_status,
|
||||||
|
windows_process.desired_stop_thread_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1362,7 +1382,7 @@ win32_process_target::write_memory (CORE_ADDR memaddr,
|
||||||
void
|
void
|
||||||
win32_process_target::request_interrupt ()
|
win32_process_target::request_interrupt ()
|
||||||
{
|
{
|
||||||
if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
|
if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, windows_process.id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* GenerateConsoleCtrlEvent can fail if process id being debugged is
|
/* GenerateConsoleCtrlEvent can fail if process id being debugged is
|
||||||
|
@ -1370,7 +1390,7 @@ win32_process_target::request_interrupt ()
|
||||||
Fallback to XP/Vista 'DebugBreakProcess', which generates a
|
Fallback to XP/Vista 'DebugBreakProcess', which generates a
|
||||||
breakpoint exception in the interior process. */
|
breakpoint exception in the interior process. */
|
||||||
|
|
||||||
if (DebugBreakProcess (current_process_handle))
|
if (DebugBreakProcess (windows_process.handle))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Last resort, suspend all threads manually. */
|
/* Last resort, suspend all threads manually. */
|
||||||
|
@ -1397,14 +1417,14 @@ win32_process_target::qxfer_siginfo (const char *annex,
|
||||||
unsigned const char *writebuf,
|
unsigned const char *writebuf,
|
||||||
CORE_ADDR offset, int len)
|
CORE_ADDR offset, int len)
|
||||||
{
|
{
|
||||||
if (siginfo_er.ExceptionCode == 0)
|
if (windows_process.siginfo_er.ExceptionCode == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (readbuf == nullptr)
|
if (readbuf == nullptr)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
char *buf = (char *) &siginfo_er;
|
char *buf = (char *) &windows_process.siginfo_er;
|
||||||
size_t bufsize = sizeof (siginfo_er);
|
size_t bufsize = sizeof (windows_process.siginfo_er);
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
EXCEPTION_RECORD32 er32;
|
EXCEPTION_RECORD32 er32;
|
||||||
|
@ -1447,7 +1467,7 @@ int
|
||||||
win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
|
win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
|
||||||
{
|
{
|
||||||
windows_thread_info *th;
|
windows_thread_info *th;
|
||||||
th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
|
||||||
if (th == NULL)
|
if (th == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if (addr != NULL)
|
if (addr != NULL)
|
||||||
|
@ -1467,8 +1487,9 @@ win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
|
||||||
bool
|
bool
|
||||||
win32_process_target::stopped_by_sw_breakpoint ()
|
win32_process_target::stopped_by_sw_breakpoint ()
|
||||||
{
|
{
|
||||||
windows_thread_info *th = thread_rec (current_thread_ptid (),
|
windows_thread_info *th
|
||||||
DONT_INVALIDATE_CONTEXT);
|
= windows_process.thread_rec (current_thread_ptid (),
|
||||||
|
DONT_INVALIDATE_CONTEXT);
|
||||||
return th == nullptr ? false : th->stopped_at_software_breakpoint;
|
return th == nullptr ? false : th->stopped_at_software_breakpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue