aboutsummaryrefslogtreecommitdiff
path: root/gdb/nat
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2022-03-31 13:41:02 -0600
committerTom Tromey <tromey@adacore.com>2022-04-04 13:58:37 -0600
commit0578e87f93b09e4cc41d3982eb1672bcfc81042d (patch)
treef2781002de2cf155a7f4cc9ae5f0c7bf08d1a270 /gdb/nat
parentfc0b013e44e5a450631706bc25612b975cfbc692 (diff)
downloadgdb-0578e87f93b09e4cc41d3982eb1672bcfc81042d.zip
gdb-0578e87f93b09e4cc41d3982eb1672bcfc81042d.tar.gz
gdb-0578e87f93b09e4cc41d3982eb1672bcfc81042d.tar.bz2
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.
Diffstat (limited to 'gdb/nat')
-rw-r--r--gdb/nat/windows-nat.c56
-rw-r--r--gdb/nat/windows-nat.h217
2 files changed, 135 insertions, 138 deletions
diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c
index 3907286..c890ee1 100644
--- a/gdb/nat/windows-nat.c
+++ b/gdb/nat/windows-nat.c
@@ -23,12 +23,6 @@
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
current_event, this is guaranteed never to come from a pending
stop. This is important because only data from the most recent
@@ -36,15 +30,6 @@ DEBUG_EVENT current_event;
ContinueDebugEvent. */
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;
DebugActiveProcessStop_ftype *DebugActiveProcessStop;
DebugBreakProcess_ftype *DebugBreakProcess;
@@ -180,7 +165,8 @@ get_image_name (HANDLE h, void *address, int unicode)
#define MS_VC_EXCEPTION 0x406d1388
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) \
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
}
-/* 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. */
+/* See nat/windows-nat.h. */
-static void
-windows_add_dll (LPVOID load_addr)
+void
+windows_process_info::add_dll (LPVOID load_addr)
{
HMODULE dummy_hmodule;
DWORD cb_needed;
@@ -353,7 +334,7 @@ windows_add_dll (LPVOID load_addr)
#ifdef __x86_64__
if (wow64_process)
{
- if (EnumProcessModulesEx (current_process_handle, &dummy_hmodule,
+ if (EnumProcessModulesEx (handle, &dummy_hmodule,
sizeof (HMODULE), &cb_needed,
LIST_MODULES_32BIT) == 0)
return;
@@ -361,7 +342,7 @@ windows_add_dll (LPVOID load_addr)
else
#endif
{
- if (EnumProcessModules (current_process_handle, &dummy_hmodule,
+ if (EnumProcessModules (handle, &dummy_hmodule,
sizeof (HMODULE), &cb_needed) == 0)
return;
}
@@ -373,7 +354,7 @@ windows_add_dll (LPVOID load_addr)
#ifdef __x86_64__
if (wow64_process)
{
- if (EnumProcessModulesEx (current_process_handle, hmodules,
+ if (EnumProcessModulesEx (handle, hmodules,
cb_needed, &cb_needed,
LIST_MODULES_32BIT) == 0)
return;
@@ -381,7 +362,7 @@ windows_add_dll (LPVOID load_addr)
else
#endif
{
- if (EnumProcessModules (current_process_handle, hmodules,
+ if (EnumProcessModules (handle, hmodules,
cb_needed, &cb_needed) == 0)
return;
}
@@ -426,11 +407,11 @@ windows_add_dll (LPVOID load_addr)
char dll_name[MAX_PATH];
#endif
const char *name;
- if (GetModuleInformation (current_process_handle, hmodules[i],
+ if (GetModuleInformation (handle, hmodules[i],
&mi, sizeof (mi)) == 0)
continue;
- if (GetModuleFileNameEx (current_process_handle, hmodules[i],
+ if (GetModuleFileNameEx (handle, hmodules[i],
dll_name, sizeof (dll_name)) == 0)
continue;
#ifdef __USEWIDE
@@ -466,7 +447,7 @@ windows_add_dll (LPVOID load_addr)
/* See nat/windows-nat.h. */
void
-dll_loaded_event ()
+windows_process_info::dll_loaded_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
particular is explicitly documented as "likely not pass[ed]"
(source: MSDN LOAD_DLL_DEBUG_INFO structure). */
- dll_name = get_image_name (current_process_handle,
- event->lpImageName, event->fUnicode);
+ dll_name = get_image_name (handle, event->lpImageName, event->fUnicode);
/* If the DLL name could not be gleaned via lpImageName, try harder
by enumerating all the DLLs loaded into the inferior, looking for
one that is loaded at base address = lpBaseOfDll. */
if (dll_name != nullptr)
handle_load_dll (dll_name, event->lpBaseOfDll);
else if (event->lpBaseOfDll != nullptr)
- windows_add_dll (event->lpBaseOfDll);
+ add_dll (event->lpBaseOfDll);
}
/* See nat/windows-nat.h. */
void
-windows_add_all_dlls ()
+windows_process_info::add_all_dlls ()
{
- windows_add_dll (nullptr);
+ add_dll (nullptr);
}
/* See nat/windows-nat.h. */
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
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. */
gdb::optional<pending_stop>
-fetch_pending_stop (bool debug_events)
+windows_process_info::fetch_pending_stop (bool debug_events)
{
gdb::optional<pending_stop> result;
for (auto iter = pending_stops.begin ();
diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h
index bfb359e..7f76ba0 100644
--- a/gdb/nat/windows-nat.h
+++ b/gdb/nat/windows-nat.h
@@ -109,145 +109,162 @@ enum thread_disposition_type
INVALIDATE_CONTEXT
};
-/* Find a thread record given a thread id. THREAD_DISPOSITION
- controls whether the thread is suspended, and whether the context
- is invalidated.
+/* A single pending stop. See "pending_stops" for more
+ information. */
+struct pending_stop
+{
+ /* The thread id. */
+ DWORD thread_id;
- This function must be supplied by the embedding application. */
-extern windows_thread_info *thread_rec (ptid_t ptid,
- thread_disposition_type disposition);
+ /* The target waitstatus we computed. */
+ target_waitstatus status;
+ /* The event. A few fields of this can be referenced after a stop,
+ and it seemed simplest to store the entire event. */
+ DEBUG_EVENT event;
+};
-/* 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.
+typedef enum
+{
+ HANDLE_EXCEPTION_UNHANDLED = 0,
+ HANDLE_EXCEPTION_HANDLED,
+ HANDLE_EXCEPTION_IGNORED
+} handle_exception_result;
- Cygwin prepends its messages with a "cygwin:". Interpret this as
- a Cygwin signal. Otherwise just print the string as a warning.
+/* A single Windows process. An object of this type (or subclass) is
+ created by the client. Some methods must be provided by the client
+ as well. */
- This function must be supplied by the embedding application. */
-extern int handle_output_debug_string (struct target_waitstatus *ourstatus);
+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;
+
+ /* The current debug event from WaitForDebugEvent or from a pending
+ stop. */
+ 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. */
+ DWORD desired_stop_thread_id = -1;
+
+ /* 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;
+
+ /* Contents of $_siginfo */
+ EXCEPTION_RECORD siginfo_er {};
-/* Handle a DLL load event.
+#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
- 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.
+ /* 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. */
+ This function must be supplied by the embedding application. */
+ windows_thread_info *thread_rec (ptid_t ptid,
+ thread_disposition_type disposition);
-extern void handle_load_dll (const char *dll_name, LPVOID base);
+ /* 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.
-/* Handle a DLL unload event.
+ Cygwin prepends its messages with a "cygwin:". Interpret this as
+ a Cygwin signal. Otherwise just print the string as a warning.
- This function assumes that this event did not occur during inferior
- initialization.
+ This function must be supplied by the embedding application. */
+ int handle_output_debug_string (struct target_waitstatus *ourstatus);
- This function must be supplied by the embedding application. */
+ /* Handle a DLL load event.
-extern void handle_unload_dll ();
+ This function assumes that the current event did not occur during
+ inferior initialization.
-/* 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.
+ DLL_NAME is the name of the library. BASE is the base load
+ address.
- Return true if the exception was handled; return false otherwise.
+ This function must be supplied by the embedding application. */
- This function must be supplied by the embedding application. */
+ void handle_load_dll (const char *dll_name, LPVOID base);
-extern bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
+ /* Handle a DLL unload event.
-/* 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". */
+ This function assumes that this event did not occur during inferior
+ initialization.
-extern bool handle_access_violation (const EXCEPTION_RECORD *rec);
+ This function must be supplied by the embedding application. */
+ void handle_unload_dll ();
-/* Currently executing process */
-extern HANDLE current_process_handle;
-extern DWORD current_process_id;
-extern DWORD main_thread_id;
-extern enum gdb_signal last_sig;
+ /* 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.
-/* The current debug event from WaitForDebugEvent or from a pending
- stop. */
-extern DEBUG_EVENT current_event;
+ Return true if the exception was handled; return false otherwise.
-/* 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;
+ This function must be supplied by the embedding application. */
-/* A single pending stop. See "pending_stops" for more
- information. */
-struct pending_stop
-{
- /* The thread id. */
- DWORD thread_id;
+ bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
- /* The target waitstatus we computed. */
- target_waitstatus status;
-
- /* The event. A few fields of this can be referenced after a stop,
- and it seemed simplest to store the entire event. */
- DEBUG_EVENT event;
-};
+ /* 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". */
-/* 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;
+ bool handle_access_violation (const EXCEPTION_RECORD *rec);
-/* Contents of $_siginfo */
-extern EXCEPTION_RECORD siginfo_er;
+ handle_exception_result handle_exception
+ (struct target_waitstatus *ourstatus, bool debug_exceptions);
-#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
+ /* Call to indicate that a DLL was loaded. */
-typedef enum
-{
- HANDLE_EXCEPTION_UNHANDLED = 0,
- HANDLE_EXCEPTION_HANDLED,
- HANDLE_EXCEPTION_IGNORED
-} handle_exception_result;
+ void dll_loaded_event ();
-extern handle_exception_result handle_exception
- (struct target_waitstatus *ourstatus, bool debug_exceptions);
+ /* Iterate over all DLLs currently mapped by our inferior, and
+ add them to our list of solibs. */
-/* Call to indicate that a DLL was loaded. */
+ void add_all_dlls ();
-extern void dll_loaded_event ();
+ /* Return true if there is a pending stop matching
+ desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
+ enabled. */
-/* Iterate over all DLLs currently mapped by our inferior, and
- add them to our list of solibs. */
+ bool matching_pending_stop (bool debug_events);
-extern void windows_add_all_dlls ();
+ /* 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. */
-/* Return true if there is a pending stop matching
- desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
- enabled. */
+ gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
-extern bool matching_pending_stop (bool debug_events);
+private:
-/* 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. */
+ /* 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. */
-extern gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
+ void add_dll (LPVOID load_addr);
+};
/* A simple wrapper for ContinueDebugEvent that continues the last
waited-for event. If DEBUG_EVENTS is true, logging will be