windows-nat.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /* Internal interfaces for the Windows code
  2. Copyright (C) 1995-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #ifndef NAT_WINDOWS_NAT_H
  15. #define NAT_WINDOWS_NAT_H
  16. #include <windows.h>
  17. #include <psapi.h>
  18. #include <vector>
  19. #include "gdbsupport/gdb_optional.h"
  20. #include "target/waitstatus.h"
  21. #define STATUS_WX86_BREAKPOINT 0x4000001F
  22. #define STATUS_WX86_SINGLE_STEP 0x4000001E
  23. namespace windows_nat
  24. {
  25. /* Thread information structure used to track extra information about
  26. each thread. */
  27. struct windows_thread_info
  28. {
  29. windows_thread_info (DWORD tid_, HANDLE h_, CORE_ADDR tlb)
  30. : tid (tid_),
  31. h (h_),
  32. thread_local_base (tlb)
  33. {
  34. }
  35. DISABLE_COPY_AND_ASSIGN (windows_thread_info);
  36. /* Ensure that this thread has been suspended. */
  37. void suspend ();
  38. /* Resume the thread if it has been suspended. */
  39. void resume ();
  40. /* The Win32 thread identifier. */
  41. DWORD tid;
  42. /* The handle to the thread. */
  43. HANDLE h;
  44. /* Thread Information Block address. */
  45. CORE_ADDR thread_local_base;
  46. /* This keeps track of whether SuspendThread was called on this
  47. thread. -1 means there was a failure or that the thread was
  48. explicitly not suspended, 1 means it was called, and 0 means it
  49. was not. */
  50. int suspended = 0;
  51. /* The context of the thread, including any manipulations. */
  52. union
  53. {
  54. CONTEXT context {};
  55. #ifdef __x86_64__
  56. WOW64_CONTEXT wow64_context;
  57. #endif
  58. };
  59. /* Whether debug registers changed since we last set CONTEXT back to
  60. the thread. */
  61. bool debug_registers_changed = false;
  62. /* Nonzero if CONTEXT is invalidated and must be re-read from the
  63. inferior thread. */
  64. bool reload_context = false;
  65. /* True if this thread is currently stopped at a software
  66. breakpoint. This is used to offset the PC when needed. */
  67. bool stopped_at_software_breakpoint = false;
  68. /* True if we've adjusted the PC after hitting a software
  69. breakpoint, false otherwise. This lets us avoid multiple
  70. adjustments if the registers are read multiple times. */
  71. bool pc_adjusted = false;
  72. /* The name of the thread, allocated by xmalloc. */
  73. gdb::unique_xmalloc_ptr<char> name;
  74. };
  75. /* Possible values to pass to 'thread_rec'. */
  76. enum thread_disposition_type
  77. {
  78. /* Do not invalidate the thread's context, and do not suspend the
  79. thread. */
  80. DONT_INVALIDATE_CONTEXT,
  81. /* Invalidate the context, but do not suspend the thread. */
  82. DONT_SUSPEND,
  83. /* Invalidate the context and suspend the thread. */
  84. INVALIDATE_CONTEXT
  85. };
  86. /* A single pending stop. See "pending_stops" for more
  87. information. */
  88. struct pending_stop
  89. {
  90. /* The thread id. */
  91. DWORD thread_id;
  92. /* The target waitstatus we computed. */
  93. target_waitstatus status;
  94. /* The event. A few fields of this can be referenced after a stop,
  95. and it seemed simplest to store the entire event. */
  96. DEBUG_EVENT event;
  97. };
  98. typedef enum
  99. {
  100. HANDLE_EXCEPTION_UNHANDLED = 0,
  101. HANDLE_EXCEPTION_HANDLED,
  102. HANDLE_EXCEPTION_IGNORED
  103. } handle_exception_result;
  104. /* A single Windows process. An object of this type (or subclass) is
  105. created by the client. Some methods must be provided by the client
  106. as well. */
  107. struct windows_process_info
  108. {
  109. /* The process handle */
  110. HANDLE handle = 0;
  111. DWORD id = 0;
  112. DWORD main_thread_id = 0;
  113. enum gdb_signal last_sig = GDB_SIGNAL_0;
  114. /* The current debug event from WaitForDebugEvent or from a pending
  115. stop. */
  116. DEBUG_EVENT current_event {};
  117. /* The ID of the thread for which we anticipate a stop event.
  118. Normally this is -1, meaning we'll accept an event in any
  119. thread. */
  120. DWORD desired_stop_thread_id = -1;
  121. /* A vector of pending stops. Sometimes, Windows will report a stop
  122. on a thread that has been ostensibly suspended. We believe what
  123. happens here is that two threads hit a breakpoint simultaneously,
  124. and the Windows kernel queues the stop events. However, this can
  125. result in the strange effect of trying to single step thread A --
  126. leaving all other threads suspended -- and then seeing a stop in
  127. thread B. To handle this scenario, we queue all such "pending"
  128. stops here, and then process them once the step has completed. See
  129. PR gdb/22992. */
  130. std::vector<pending_stop> pending_stops;
  131. /* Contents of $_siginfo */
  132. EXCEPTION_RECORD siginfo_er {};
  133. #ifdef __x86_64__
  134. /* The target is a WOW64 process */
  135. bool wow64_process = false;
  136. /* Ignore first breakpoint exception of WOW64 process */
  137. bool ignore_first_breakpoint = false;
  138. #endif
  139. /* Find a thread record given a thread id. THREAD_DISPOSITION
  140. controls whether the thread is suspended, and whether the context
  141. is invalidated.
  142. This function must be supplied by the embedding application. */
  143. windows_thread_info *thread_rec (ptid_t ptid,
  144. thread_disposition_type disposition);
  145. /* Handle OUTPUT_DEBUG_STRING_EVENT from child process. Updates
  146. OURSTATUS and returns the thread id if this represents a thread
  147. change (this is specific to Cygwin), otherwise 0.
  148. Cygwin prepends its messages with a "cygwin:". Interpret this as
  149. a Cygwin signal. Otherwise just print the string as a warning.
  150. This function must be supplied by the embedding application. */
  151. int handle_output_debug_string (struct target_waitstatus *ourstatus);
  152. /* Handle a DLL load event.
  153. This function assumes that the current event did not occur during
  154. inferior initialization.
  155. DLL_NAME is the name of the library. BASE is the base load
  156. address.
  157. This function must be supplied by the embedding application. */
  158. void handle_load_dll (const char *dll_name, LPVOID base);
  159. /* Handle a DLL unload event.
  160. This function assumes that this event did not occur during inferior
  161. initialization.
  162. This function must be supplied by the embedding application. */
  163. void handle_unload_dll ();
  164. /* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
  165. somewhat undocumented but is used to tell the debugger the name of
  166. a thread.
  167. Return true if the exception was handled; return false otherwise.
  168. This function must be supplied by the embedding application. */
  169. bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
  170. /* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding
  171. application a chance to change it to be considered "unhandled".
  172. This function must be supplied by the embedding application. If it
  173. returns true, then the exception is "unhandled". */
  174. bool handle_access_violation (const EXCEPTION_RECORD *rec);
  175. handle_exception_result handle_exception
  176. (struct target_waitstatus *ourstatus, bool debug_exceptions);
  177. /* Call to indicate that a DLL was loaded. */
  178. void dll_loaded_event ();
  179. /* Iterate over all DLLs currently mapped by our inferior, and
  180. add them to our list of solibs. */
  181. void add_all_dlls ();
  182. /* Return true if there is a pending stop matching
  183. desired_stop_thread_id. If DEBUG_EVENTS is true, logging will be
  184. enabled. */
  185. bool matching_pending_stop (bool debug_events);
  186. /* See if a pending stop matches DESIRED_STOP_THREAD_ID. If so,
  187. remove it from the list of pending stops, set 'current_event', and
  188. return it. Otherwise, return an empty optional. */
  189. gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
  190. private:
  191. /* Iterate over all DLLs currently mapped by our inferior, looking for
  192. a DLL which is loaded at LOAD_ADDR. If found, add the DLL to our
  193. list of solibs; otherwise do nothing. LOAD_ADDR NULL means add all
  194. DLLs to the list of solibs; this is used when the inferior finishes
  195. its initialization, and all the DLLs it statically depends on are
  196. presumed loaded. */
  197. void add_dll (LPVOID load_addr);
  198. };
  199. /* A simple wrapper for ContinueDebugEvent that continues the last
  200. waited-for event. If DEBUG_EVENTS is true, logging will be
  201. enabled. */
  202. extern BOOL continue_last_debug_event (DWORD continue_status,
  203. bool debug_events);
  204. /* A simple wrapper for WaitForDebugEvent that also sets the internal
  205. 'last_wait_event' on success. */
  206. extern BOOL wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout);
  207. #define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
  208. #define DebugActiveProcessStop dyn_DebugActiveProcessStop
  209. #define DebugBreakProcess dyn_DebugBreakProcess
  210. #define DebugSetProcessKillOnExit dyn_DebugSetProcessKillOnExit
  211. #define EnumProcessModules dyn_EnumProcessModules
  212. #define EnumProcessModulesEx dyn_EnumProcessModulesEx
  213. #define GetModuleInformation dyn_GetModuleInformation
  214. #define GetModuleFileNameExA dyn_GetModuleFileNameExA
  215. #define GetModuleFileNameExW dyn_GetModuleFileNameExW
  216. #define LookupPrivilegeValueA dyn_LookupPrivilegeValueA
  217. #define OpenProcessToken dyn_OpenProcessToken
  218. #define GetConsoleFontSize dyn_GetConsoleFontSize
  219. #define GetCurrentConsoleFont dyn_GetCurrentConsoleFont
  220. #define Wow64SuspendThread dyn_Wow64SuspendThread
  221. #define Wow64GetThreadContext dyn_Wow64GetThreadContext
  222. #define Wow64SetThreadContext dyn_Wow64SetThreadContext
  223. #define Wow64GetThreadSelectorEntry dyn_Wow64GetThreadSelectorEntry
  224. #define GenerateConsoleCtrlEvent dyn_GenerateConsoleCtrlEvent
  225. typedef BOOL WINAPI (AdjustTokenPrivileges_ftype) (HANDLE, BOOL,
  226. PTOKEN_PRIVILEGES,
  227. DWORD, PTOKEN_PRIVILEGES,
  228. PDWORD);
  229. extern AdjustTokenPrivileges_ftype *AdjustTokenPrivileges;
  230. typedef BOOL WINAPI (DebugActiveProcessStop_ftype) (DWORD);
  231. extern DebugActiveProcessStop_ftype *DebugActiveProcessStop;
  232. typedef BOOL WINAPI (DebugBreakProcess_ftype) (HANDLE);
  233. extern DebugBreakProcess_ftype *DebugBreakProcess;
  234. typedef BOOL WINAPI (DebugSetProcessKillOnExit_ftype) (BOOL);
  235. extern DebugSetProcessKillOnExit_ftype *DebugSetProcessKillOnExit;
  236. typedef BOOL WINAPI (EnumProcessModules_ftype) (HANDLE, HMODULE *, DWORD,
  237. LPDWORD);
  238. extern EnumProcessModules_ftype *EnumProcessModules;
  239. #ifdef __x86_64__
  240. typedef BOOL WINAPI (EnumProcessModulesEx_ftype) (HANDLE, HMODULE *, DWORD,
  241. LPDWORD, DWORD);
  242. extern EnumProcessModulesEx_ftype *EnumProcessModulesEx;
  243. #endif
  244. typedef BOOL WINAPI (GetModuleInformation_ftype) (HANDLE, HMODULE,
  245. LPMODULEINFO, DWORD);
  246. extern GetModuleInformation_ftype *GetModuleInformation;
  247. typedef DWORD WINAPI (GetModuleFileNameExA_ftype) (HANDLE, HMODULE, LPSTR,
  248. DWORD);
  249. extern GetModuleFileNameExA_ftype *GetModuleFileNameExA;
  250. typedef DWORD WINAPI (GetModuleFileNameExW_ftype) (HANDLE, HMODULE,
  251. LPWSTR, DWORD);
  252. extern GetModuleFileNameExW_ftype *GetModuleFileNameExW;
  253. typedef BOOL WINAPI (LookupPrivilegeValueA_ftype) (LPCSTR, LPCSTR, PLUID);
  254. extern LookupPrivilegeValueA_ftype *LookupPrivilegeValueA;
  255. typedef BOOL WINAPI (OpenProcessToken_ftype) (HANDLE, DWORD, PHANDLE);
  256. extern OpenProcessToken_ftype *OpenProcessToken;
  257. typedef BOOL WINAPI (GetCurrentConsoleFont_ftype) (HANDLE, BOOL,
  258. CONSOLE_FONT_INFO *);
  259. extern GetCurrentConsoleFont_ftype *GetCurrentConsoleFont;
  260. typedef COORD WINAPI (GetConsoleFontSize_ftype) (HANDLE, DWORD);
  261. extern GetConsoleFontSize_ftype *GetConsoleFontSize;
  262. #ifdef __x86_64__
  263. typedef DWORD WINAPI (Wow64SuspendThread_ftype) (HANDLE);
  264. extern Wow64SuspendThread_ftype *Wow64SuspendThread;
  265. typedef BOOL WINAPI (Wow64GetThreadContext_ftype) (HANDLE, PWOW64_CONTEXT);
  266. extern Wow64GetThreadContext_ftype *Wow64GetThreadContext;
  267. typedef BOOL WINAPI (Wow64SetThreadContext_ftype) (HANDLE,
  268. const WOW64_CONTEXT *);
  269. extern Wow64SetThreadContext_ftype *Wow64SetThreadContext;
  270. typedef BOOL WINAPI (Wow64GetThreadSelectorEntry_ftype) (HANDLE, DWORD,
  271. PLDT_ENTRY);
  272. extern Wow64GetThreadSelectorEntry_ftype *Wow64GetThreadSelectorEntry;
  273. #endif
  274. typedef BOOL WINAPI (GenerateConsoleCtrlEvent_ftype) (DWORD, DWORD);
  275. extern GenerateConsoleCtrlEvent_ftype *GenerateConsoleCtrlEvent;
  276. /* Load any functions which may not be available in ancient versions
  277. of Windows. */
  278. extern bool initialize_loadable ();
  279. }
  280. #endif