Home | History | Annotate | Line # | Download | only in nat
windows-nat.h revision 1.1
      1  1.1  christos /* Internal interfaces for the Windows code
      2  1.1  christos    Copyright (C) 1995-2020 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    This file is part of GDB.
      5  1.1  christos 
      6  1.1  christos    This program is free software; you can redistribute it and/or modify
      7  1.1  christos    it under the terms of the GNU General Public License as published by
      8  1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9  1.1  christos    (at your option) any later version.
     10  1.1  christos 
     11  1.1  christos    This program is distributed in the hope that it will be useful,
     12  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1  christos    GNU General Public License for more details.
     15  1.1  christos 
     16  1.1  christos    You should have received a copy of the GNU General Public License
     17  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18  1.1  christos 
     19  1.1  christos #ifndef NAT_WINDOWS_NAT_H
     20  1.1  christos #define NAT_WINDOWS_NAT_H
     21  1.1  christos 
     22  1.1  christos #include <windows.h>
     23  1.1  christos #include <vector>
     24  1.1  christos 
     25  1.1  christos #include "gdbsupport/gdb_optional.h"
     26  1.1  christos #include "target/waitstatus.h"
     27  1.1  christos 
     28  1.1  christos #define STATUS_WX86_BREAKPOINT 0x4000001F
     29  1.1  christos #define STATUS_WX86_SINGLE_STEP 0x4000001E
     30  1.1  christos 
     31  1.1  christos namespace windows_nat
     32  1.1  christos {
     33  1.1  christos 
     34  1.1  christos /* Thread information structure used to track extra information about
     35  1.1  christos    each thread.  */
     36  1.1  christos struct windows_thread_info
     37  1.1  christos {
     38  1.1  christos   windows_thread_info (DWORD tid_, HANDLE h_, CORE_ADDR tlb)
     39  1.1  christos     : tid (tid_),
     40  1.1  christos       h (h_),
     41  1.1  christos       thread_local_base (tlb)
     42  1.1  christos   {
     43  1.1  christos   }
     44  1.1  christos 
     45  1.1  christos   ~windows_thread_info ();
     46  1.1  christos 
     47  1.1  christos   DISABLE_COPY_AND_ASSIGN (windows_thread_info);
     48  1.1  christos 
     49  1.1  christos   /* Ensure that this thread has been suspended.  */
     50  1.1  christos   void suspend ();
     51  1.1  christos 
     52  1.1  christos   /* Resume the thread if it has been suspended.  */
     53  1.1  christos   void resume ();
     54  1.1  christos 
     55  1.1  christos   /* The Win32 thread identifier.  */
     56  1.1  christos   DWORD tid;
     57  1.1  christos 
     58  1.1  christos   /* The handle to the thread.  */
     59  1.1  christos   HANDLE h;
     60  1.1  christos 
     61  1.1  christos   /* Thread Information Block address.  */
     62  1.1  christos   CORE_ADDR thread_local_base;
     63  1.1  christos 
     64  1.1  christos   /* This keeps track of whether SuspendThread was called on this
     65  1.1  christos      thread.  -1 means there was a failure or that the thread was
     66  1.1  christos      explicitly not suspended, 1 means it was called, and 0 means it
     67  1.1  christos      was not.  */
     68  1.1  christos   int suspended = 0;
     69  1.1  christos 
     70  1.1  christos #ifdef _WIN32_WCE
     71  1.1  christos   /* The context as retrieved right after suspending the thread. */
     72  1.1  christos   CONTEXT base_context {};
     73  1.1  christos #endif
     74  1.1  christos 
     75  1.1  christos   /* The context of the thread, including any manipulations.  */
     76  1.1  christos   union
     77  1.1  christos   {
     78  1.1  christos     CONTEXT context {};
     79  1.1  christos #ifdef __x86_64__
     80  1.1  christos     WOW64_CONTEXT wow64_context;
     81  1.1  christos #endif
     82  1.1  christos   };
     83  1.1  christos 
     84  1.1  christos   /* Whether debug registers changed since we last set CONTEXT back to
     85  1.1  christos      the thread.  */
     86  1.1  christos   bool debug_registers_changed = false;
     87  1.1  christos 
     88  1.1  christos   /* Nonzero if CONTEXT is invalidated and must be re-read from the
     89  1.1  christos      inferior thread.  */
     90  1.1  christos   bool reload_context = false;
     91  1.1  christos 
     92  1.1  christos   /* True if this thread is currently stopped at a software
     93  1.1  christos      breakpoint.  This is used to offset the PC when needed.  */
     94  1.1  christos   bool stopped_at_software_breakpoint = false;
     95  1.1  christos 
     96  1.1  christos   /* True if we've adjusted the PC after hitting a software
     97  1.1  christos      breakpoint, false otherwise.  This lets us avoid multiple
     98  1.1  christos      adjustments if the registers are read multiple times.  */
     99  1.1  christos   bool pc_adjusted = false;
    100  1.1  christos 
    101  1.1  christos   /* The name of the thread, allocated by xmalloc.  */
    102  1.1  christos   gdb::unique_xmalloc_ptr<char> name;
    103  1.1  christos };
    104  1.1  christos 
    105  1.1  christos 
    106  1.1  christos /* Possible values to pass to 'thread_rec'.  */
    107  1.1  christos enum thread_disposition_type
    108  1.1  christos {
    109  1.1  christos   /* Do not invalidate the thread's context, and do not suspend the
    110  1.1  christos      thread.  */
    111  1.1  christos   DONT_INVALIDATE_CONTEXT,
    112  1.1  christos   /* Invalidate the context, but do not suspend the thread.  */
    113  1.1  christos   DONT_SUSPEND,
    114  1.1  christos   /* Invalidate the context and suspend the thread.  */
    115  1.1  christos   INVALIDATE_CONTEXT
    116  1.1  christos };
    117  1.1  christos 
    118  1.1  christos /* Find a thread record given a thread id.  THREAD_DISPOSITION
    119  1.1  christos    controls whether the thread is suspended, and whether the context
    120  1.1  christos    is invalidated.
    121  1.1  christos 
    122  1.1  christos    This function must be supplied by the embedding application.  */
    123  1.1  christos extern windows_thread_info *thread_rec (ptid_t ptid,
    124  1.1  christos 					thread_disposition_type disposition);
    125  1.1  christos 
    126  1.1  christos 
    127  1.1  christos /* Handle OUTPUT_DEBUG_STRING_EVENT from child process.  Updates
    128  1.1  christos    OURSTATUS and returns the thread id if this represents a thread
    129  1.1  christos    change (this is specific to Cygwin), otherwise 0.
    130  1.1  christos 
    131  1.1  christos    Cygwin prepends its messages with a "cygwin:".  Interpret this as
    132  1.1  christos    a Cygwin signal.  Otherwise just print the string as a warning.
    133  1.1  christos 
    134  1.1  christos    This function must be supplied by the embedding application.  */
    135  1.1  christos extern int handle_output_debug_string (struct target_waitstatus *ourstatus);
    136  1.1  christos 
    137  1.1  christos /* Handle a DLL load event.
    138  1.1  christos 
    139  1.1  christos    This function assumes that the current event did not occur during
    140  1.1  christos    inferior initialization.
    141  1.1  christos 
    142  1.1  christos    This function must be supplied by the embedding application.  */
    143  1.1  christos 
    144  1.1  christos extern void handle_load_dll ();
    145  1.1  christos 
    146  1.1  christos /* Handle a DLL unload event.
    147  1.1  christos 
    148  1.1  christos    This function assumes that this event did not occur during inferior
    149  1.1  christos    initialization.
    150  1.1  christos 
    151  1.1  christos    This function must be supplied by the embedding application.  */
    152  1.1  christos 
    153  1.1  christos extern void handle_unload_dll ();
    154  1.1  christos 
    155  1.1  christos /* Handle MS_VC_EXCEPTION when processing a stop.  MS_VC_EXCEPTION is
    156  1.1  christos    somewhat undocumented but is used to tell the debugger the name of
    157  1.1  christos    a thread.
    158  1.1  christos 
    159  1.1  christos    Return true if the exception was handled; return false otherwise.
    160  1.1  christos 
    161  1.1  christos    This function must be supplied by the embedding application.  */
    162  1.1  christos 
    163  1.1  christos extern bool handle_ms_vc_exception (const EXCEPTION_RECORD *rec);
    164  1.1  christos 
    165  1.1  christos /* When EXCEPTION_ACCESS_VIOLATION is processed, we give the embedding
    166  1.1  christos    application a chance to change it to be considered "unhandled".
    167  1.1  christos    This function must be supplied by the embedding application.  If it
    168  1.1  christos    returns true, then the exception is "unhandled".  */
    169  1.1  christos 
    170  1.1  christos extern bool handle_access_violation (const EXCEPTION_RECORD *rec);
    171  1.1  christos 
    172  1.1  christos 
    173  1.1  christos /* Currently executing process */
    174  1.1  christos extern HANDLE current_process_handle;
    175  1.1  christos extern DWORD current_process_id;
    176  1.1  christos extern DWORD main_thread_id;
    177  1.1  christos extern enum gdb_signal last_sig;
    178  1.1  christos 
    179  1.1  christos /* The current debug event from WaitForDebugEvent or from a pending
    180  1.1  christos    stop.  */
    181  1.1  christos extern DEBUG_EVENT current_event;
    182  1.1  christos 
    183  1.1  christos /* The ID of the thread for which we anticipate a stop event.
    184  1.1  christos    Normally this is -1, meaning we'll accept an event in any
    185  1.1  christos    thread.  */
    186  1.1  christos extern DWORD desired_stop_thread_id;
    187  1.1  christos 
    188  1.1  christos /* A single pending stop.  See "pending_stops" for more
    189  1.1  christos    information.  */
    190  1.1  christos struct pending_stop
    191  1.1  christos {
    192  1.1  christos   /* The thread id.  */
    193  1.1  christos   DWORD thread_id;
    194  1.1  christos 
    195  1.1  christos   /* The target waitstatus we computed.  */
    196  1.1  christos   target_waitstatus status;
    197  1.1  christos 
    198  1.1  christos   /* The event.  A few fields of this can be referenced after a stop,
    199  1.1  christos      and it seemed simplest to store the entire event.  */
    200  1.1  christos   DEBUG_EVENT event;
    201  1.1  christos };
    202  1.1  christos 
    203  1.1  christos /* A vector of pending stops.  Sometimes, Windows will report a stop
    204  1.1  christos    on a thread that has been ostensibly suspended.  We believe what
    205  1.1  christos    happens here is that two threads hit a breakpoint simultaneously,
    206  1.1  christos    and the Windows kernel queues the stop events.  However, this can
    207  1.1  christos    result in the strange effect of trying to single step thread A --
    208  1.1  christos    leaving all other threads suspended -- and then seeing a stop in
    209  1.1  christos    thread B.  To handle this scenario, we queue all such "pending"
    210  1.1  christos    stops here, and then process them once the step has completed.  See
    211  1.1  christos    PR gdb/22992.  */
    212  1.1  christos extern std::vector<pending_stop> pending_stops;
    213  1.1  christos 
    214  1.1  christos /* Contents of $_siginfo */
    215  1.1  christos extern EXCEPTION_RECORD siginfo_er;
    216  1.1  christos 
    217  1.1  christos #ifdef __x86_64__
    218  1.1  christos /* Ignore first breakpoint exception of WOW64 process */
    219  1.1  christos extern bool ignore_first_breakpoint;
    220  1.1  christos #endif
    221  1.1  christos 
    222  1.1  christos /* Return the name of the DLL referenced by H at ADDRESS.  UNICODE
    223  1.1  christos    determines what sort of string is read from the inferior.  Returns
    224  1.1  christos    the name of the DLL, or NULL on error.  If a name is returned, it
    225  1.1  christos    is stored in a static buffer which is valid until the next call to
    226  1.1  christos    get_image_name.  */
    227  1.1  christos extern const char *get_image_name (HANDLE h, void *address, int unicode);
    228  1.1  christos 
    229  1.1  christos typedef enum
    230  1.1  christos {
    231  1.1  christos   HANDLE_EXCEPTION_UNHANDLED = 0,
    232  1.1  christos   HANDLE_EXCEPTION_HANDLED,
    233  1.1  christos   HANDLE_EXCEPTION_IGNORED
    234  1.1  christos } handle_exception_result;
    235  1.1  christos 
    236  1.1  christos extern handle_exception_result handle_exception
    237  1.1  christos   (struct target_waitstatus *ourstatus, bool debug_exceptions);
    238  1.1  christos 
    239  1.1  christos /* Return true if there is a pending stop matching
    240  1.1  christos    desired_stop_thread_id.  If DEBUG_EVENTS is true, logging will be
    241  1.1  christos    enabled.  */
    242  1.1  christos 
    243  1.1  christos extern bool matching_pending_stop (bool debug_events);
    244  1.1  christos 
    245  1.1  christos /* See if a pending stop matches DESIRED_STOP_THREAD_ID.  If so,
    246  1.1  christos    remove it from the list of pending stops, set 'current_event', and
    247  1.1  christos    return it.  Otherwise, return an empty optional.  */
    248  1.1  christos 
    249  1.1  christos extern gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
    250  1.1  christos 
    251  1.1  christos /* A simple wrapper for ContinueDebugEvent that continues the last
    252  1.1  christos    waited-for event.  If DEBUG_EVENTS is true, logging will be
    253  1.1  christos    enabled.  */
    254  1.1  christos 
    255  1.1  christos extern BOOL continue_last_debug_event (DWORD continue_status,
    256  1.1  christos 				       bool debug_events);
    257  1.1  christos 
    258  1.1  christos /* A simple wrapper for WaitForDebugEvent that also sets the internal
    259  1.1  christos    'last_wait_event' on success.  */
    260  1.1  christos 
    261  1.1  christos extern BOOL wait_for_debug_event (DEBUG_EVENT *event, DWORD timeout);
    262  1.1  christos 
    263  1.1  christos }
    264  1.1  christos 
    265  1.1  christos #endif
    266