PowerPC64 DT_RELR ELFv1
[binutils-gdb.git] / gdbserver / win32-low.cc
index 39a6848307acb74b9dd2370a1216134e819694de..e19bc2bd6e8501298048f2ec3d5d9c4696906833 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface to Windows debugging, for gdbserver.
-   Copyright (C) 2006-2021 Free Software Foundation, Inc.
+   Copyright (C) 2006-2022 Free Software Foundation, Inc.
 
    Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
 
@@ -62,9 +62,6 @@ using namespace windows_nat;
 #define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
 #endif
 
-#define GETPROCADDRESS(DLL, PROC) \
-  ((winapi_ ## PROC) GetProcAddress (DLL, #PROC))
-
 int using_threads = 1;
 
 /* Globals.  */
@@ -93,21 +90,6 @@ const struct target_desc *wow64_win32_tdesc;
 
 #define NUM_REGS (the_low_target.num_regs ())
 
-typedef BOOL (WINAPI *winapi_DebugActiveProcessStop) (DWORD dwProcessId);
-typedef BOOL (WINAPI *winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
-typedef BOOL (WINAPI *winapi_DebugBreakProcess) (HANDLE);
-typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
-
-#ifdef __x86_64__
-typedef BOOL (WINAPI *winapi_Wow64SetThreadContext) (HANDLE,
-                                                    const WOW64_CONTEXT *);
-
-winapi_Wow64GetThreadContext win32_Wow64GetThreadContext;
-static winapi_Wow64SetThreadContext win32_Wow64SetThreadContext;
-#endif
-
-static void win32_add_all_dlls (void);
-
 /* Get the thread ID from the current selected inferior (the current
    thread).  */
 static ptid_t
@@ -144,7 +126,7 @@ win32_set_thread_context (windows_thread_info *th)
 {
 #ifdef __x86_64__
   if (wow64_process)
-    win32_Wow64SetThreadContext (th->h, &th->wow64_context);
+    Wow64SetThreadContext (th->h, &th->wow64_context);
   else
 #endif
     SetThreadContext (th->h, &th->context);
@@ -372,8 +354,8 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
   wow64_process = wow64;
 
   if (wow64_process
-      && (win32_Wow64GetThreadContext == nullptr
-         || win32_Wow64SetThreadContext == nullptr))
+      && (Wow64GetThreadContext == nullptr
+         || Wow64SetThreadContext == nullptr))
     error ("WOW64 debugging is not supported on this system.\n");
 
   ignore_first_breakpoint = !attached && wow64_process;
@@ -392,7 +374,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
   if (the_low_target.initial_stuff != NULL)
     (*the_low_target.initial_stuff) ();
 
-  cached_status.kind = TARGET_WAITKIND_IGNORE;
+  cached_status.set_ignore ();
 
   /* Flush all currently pending debug events (thread and dll list) up
      to the initial breakpoint.  */
@@ -403,7 +385,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
       the_target->wait (minus_one_ptid, &status, 0);
 
       /* Note win32_wait doesn't return thread events.  */
-      if (status.kind != TARGET_WAITKIND_LOADED)
+      if (status.kind () != TARGET_WAITKIND_LOADED)
        {
          cached_status = status;
          break;
@@ -435,7 +417,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
      Rather than try to work around this sort of issue, it is much
      simpler to just ignore DLL load/unload events during the startup
      phase, and then process them all in one batch now.  */
-  win32_add_all_dlls ();
+  windows_add_all_dlls ();
 
   child_initialization_done = 1;
 }
@@ -577,7 +559,7 @@ static BOOL
 create_process (const char *program, char *args,
                DWORD flags, PROCESS_INFORMATION *pi)
 {
-  const char *inferior_cwd = get_inferior_cwd ();
+  const std::string &inferior_cwd = get_inferior_cwd ();
   BOOL ret;
   size_t argslen, proglen;
 
@@ -598,9 +580,9 @@ create_process (const char *program, char *args,
                        flags,             /* start flags */
                        NULL,              /* environment */
                        /* current directory */
-                       (inferior_cwd == NULL
+                       (inferior_cwd.empty ()
                         ? NULL
-                        : gdb_tilde_expand (inferior_cwd).c_str()),
+                        : gdb_tilde_expand (inferior_cwd.c_str ()).c_str()),
                        &si,               /* start info */
                        pi);               /* proc info */
 
@@ -704,18 +686,14 @@ int
 win32_process_target::attach (unsigned long pid)
 {
   HANDLE h;
-  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
   DWORD err;
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
 
   h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
   if (h != NULL)
     {
       if (DebugActiveProcess (pid))
        {
-         if (DebugSetProcessKillOnExit != NULL)
-           DebugSetProcessKillOnExit (FALSE);
+         DebugSetProcessKillOnExit (FALSE);
 
          /* win32_wait needs to know we're attaching.  */
          attaching = 1;
@@ -822,23 +800,11 @@ win32_process_target::kill (process_info *process)
 int
 win32_process_target::detach (process_info *process)
 {
-  winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
-  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
-  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
-
-  if (DebugSetProcessKillOnExit == NULL
-      || DebugActiveProcessStop == NULL)
-    return -1;
-
-  {
-    struct thread_resume resume;
-    resume.thread = minus_one_ptid;
-    resume.kind = resume_continue;
-    resume.sig = 0;
-    this->resume (&resume, 1);
-  }
+  struct thread_resume resume;
+  resume.thread = minus_one_ptid;
+  resume.kind = resume_continue;
+  resume.sig = 0;
+  this->resume (&resume, 1);
 
   if (!DebugActiveProcessStop (current_process_id))
     return -1;
@@ -969,9 +935,13 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
   child_continue (continue_status, tid);
 }
 
-static void
-win32_add_one_solib (const char *name, CORE_ADDR load_addr)
+/* See nat/windows-nat.h.  */
+
+void
+windows_nat::handle_load_dll (const char *name, LPVOID base)
 {
+  CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
+
   char buf[MAX_PATH + 1];
   char buf2[MAX_PATH + 1];
 
@@ -1019,217 +989,6 @@ win32_add_one_solib (const char *name, CORE_ADDR load_addr)
   loaded_dll (buf2, load_addr);
 }
 
-typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
-                                                 DWORD, LPDWORD);
-#ifdef __x86_64__
-typedef BOOL (WINAPI *winapi_EnumProcessModulesEx) (HANDLE, HMODULE *, DWORD,
-                                                   LPDWORD, DWORD);
-#endif
-typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
-                                                   LPMODULEINFO, DWORD);
-typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
-                                                    LPSTR, DWORD);
-
-static winapi_EnumProcessModules win32_EnumProcessModules;
-#ifdef __x86_64__
-static winapi_EnumProcessModulesEx win32_EnumProcessModulesEx;
-#endif
-static winapi_GetModuleInformation win32_GetModuleInformation;
-static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
-
-static BOOL
-load_psapi (void)
-{
-  static int psapi_loaded = 0;
-  static HMODULE dll = NULL;
-
-  if (!psapi_loaded)
-    {
-      psapi_loaded = 1;
-      dll = LoadLibrary (TEXT("psapi.dll"));
-      if (!dll)
-       return FALSE;
-      win32_EnumProcessModules =
-             GETPROCADDRESS (dll, EnumProcessModules);
-#ifdef __x86_64__
-      win32_EnumProcessModulesEx =
-             GETPROCADDRESS (dll, EnumProcessModulesEx);
-#endif
-      win32_GetModuleInformation =
-             GETPROCADDRESS (dll, GetModuleInformation);
-      win32_GetModuleFileNameExA =
-             GETPROCADDRESS (dll, GetModuleFileNameExA);
-    }
-
-#ifdef __x86_64__
-  if (wow64_process && win32_EnumProcessModulesEx == nullptr)
-    return FALSE;
-#endif
-
-  return (win32_EnumProcessModules != NULL
-         && win32_GetModuleInformation != NULL
-         && win32_GetModuleFileNameExA != NULL);
-}
-
-/* Iterate over all DLLs currently mapped by our inferior, looking for
-   a DLL loaded at LOAD_ADDR; if found, return its file name,
-   otherwise return NULL.  If LOAD_ADDR is NULL, add all mapped DLLs
-   to our list of solibs.  */
-
-static char *
-win32_add_dll (LPVOID load_addr)
-{
-  size_t i;
-  HMODULE dh_buf[1];
-  HMODULE *DllHandle = dh_buf;
-  DWORD cbNeeded;
-  BOOL ok;
-
-  if (!load_psapi ())
-    return NULL;
-
-  cbNeeded = 0;
-#ifdef __x86_64__
-  if (wow64_process)
-    ok = (*win32_EnumProcessModulesEx) (current_process_handle,
-                                       DllHandle,
-                                       sizeof (HMODULE),
-                                       &cbNeeded,
-                                       LIST_MODULES_32BIT);
-  else
-#endif
-    ok = (*win32_EnumProcessModules) (current_process_handle,
-                                     DllHandle,
-                                     sizeof (HMODULE),
-                                     &cbNeeded);
-
-  if (!ok || !cbNeeded)
-    return NULL;
-
-  DllHandle = (HMODULE *) alloca (cbNeeded);
-  if (!DllHandle)
-    return NULL;
-
-#ifdef __x86_64__
-  if (wow64_process)
-    ok = (*win32_EnumProcessModulesEx) (current_process_handle,
-                                       DllHandle,
-                                       cbNeeded,
-                                       &cbNeeded,
-                                       LIST_MODULES_32BIT);
-  else
-#endif
-    ok = (*win32_EnumProcessModules) (current_process_handle,
-                                     DllHandle,
-                                     cbNeeded,
-                                     &cbNeeded);
-  if (!ok)
-    return NULL;
-
-  char system_dir[MAX_PATH];
-  char syswow_dir[MAX_PATH];
-  size_t system_dir_len = 0;
-  bool convert_syswow_dir = false;
-#ifdef __x86_64__
-  if (wow64_process)
-#endif
-    {
-      /* This fails on 32bit Windows because it has no SysWOW64 directory,
-        and in this case a path conversion isn't necessary.  */
-      UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
-      if (len > 0)
-       {
-         /* Check that we have passed a large enough buffer.  */
-         gdb_assert (len < sizeof (syswow_dir));
-
-         len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
-         /* Error check.  */
-         gdb_assert (len != 0);
-         /* Check that we have passed a large enough buffer.  */
-         gdb_assert (len < sizeof (system_dir));
-
-         strcat (system_dir, "\\");
-         strcat (syswow_dir, "\\");
-         system_dir_len = strlen (system_dir);
-
-         convert_syswow_dir = true;
-       }
-
-    }
-
-  for (i = 1; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
-    {
-      MODULEINFO mi;
-      static char dll_name[MAX_PATH];
-
-      if (!(*win32_GetModuleInformation) (current_process_handle,
-                                         DllHandle[i],
-                                         &mi,
-                                         sizeof (mi)))
-       continue;
-      if ((*win32_GetModuleFileNameExA) (current_process_handle,
-                                        DllHandle[i],
-                                        dll_name,
-                                        MAX_PATH) == 0)
-       continue;
-
-      if (load_addr != nullptr && mi.lpBaseOfDll != load_addr)
-       continue;
-
-      const char *name = dll_name;
-      /* Convert the DLL path of 32bit processes returned by
-        GetModuleFileNameEx from the 64bit system directory to the
-        32bit syswow64 directory if necessary.  */
-      std::string syswow_dll_path;
-      if (convert_syswow_dir
-         && strncasecmp (dll_name, system_dir, system_dir_len) == 0
-         && strchr (dll_name + system_dir_len, '\\') == nullptr)
-       {
-         syswow_dll_path = syswow_dir;
-         syswow_dll_path += dll_name + system_dir_len;
-         name = syswow_dll_path.c_str();
-       }
-
-      if (load_addr != nullptr)
-       {
-         if (name != dll_name)
-           strcpy (dll_name, name);
-         return dll_name;
-       }
-      else
-       win32_add_one_solib (name, (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll);
-    }
-  return NULL;
-}
-
-/* Iterate over all DLLs currently mapped by our inferior, and
-   add them to our list of solibs.  */
-
-static void
-win32_add_all_dlls (void)
-{
-  win32_add_dll (NULL);
-}
-
-/* See nat/windows-nat.h.  */
-
-void
-windows_nat::handle_load_dll ()
-{
-  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
-  const char *dll_name;
-
-  dll_name = get_image_name (current_process_handle,
-                            event->lpImageName, event->fUnicode);
-  if (dll_name == nullptr
-      && event->lpBaseOfDll != nullptr)
-    dll_name = win32_add_dll (event->lpBaseOfDll);
-  if (dll_name == nullptr)
-    return;
-
-  win32_add_one_solib (dll_name, (CORE_ADDR) (uintptr_t) event->lpBaseOfDll);
-}
-
 /* See nat/windows-nat.h.  */
 
 void
@@ -1322,7 +1081,7 @@ get_child_debug_event (DWORD *continue_status,
   ptid_t ptid;
 
   last_sig = GDB_SIGNAL_0;
-  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  ourstatus->set_spurious ();
   *continue_status = DBG_CONTINUE;
 
   /* Check if GDB sent us an interrupt request.  */
@@ -1343,7 +1102,7 @@ get_child_debug_event (DWORD *continue_status,
        *ourstatus = stop->status;
        current_event = stop->event;
        ptid = debug_event_ptid (&current_event);
-       current_thread = find_thread_ptid (ptid);
+       switch_to_thread (find_thread_ptid (ptid));
        return 1;
       }
 
@@ -1360,8 +1119,7 @@ get_child_debug_event (DWORD *continue_status,
               load the application, e.g., if the main executable
               tries to pull in a non-existing export from a
               DLL.  */
-           ourstatus->kind = TARGET_WAITKIND_EXITED;
-           ourstatus->value.integer = 1;
+           ourstatus->set_exited (1);
            return 1;
          }
 
@@ -1394,7 +1152,7 @@ get_child_debug_event (DWORD *continue_status,
       child_delete_thread (current_event.dwProcessId,
                           current_event.dwThreadId);
 
-      current_thread = get_first_thread ();
+      switch_to_thread (get_first_thread ());
       return 1;
 
     case CREATE_PROCESS_DEBUG_EVENT:
@@ -1433,15 +1191,9 @@ get_child_debug_event (DWORD *continue_status,
        int exit_signal
          = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
        if (exit_signal == -1)
-         {
-           ourstatus->kind = TARGET_WAITKIND_EXITED;
-           ourstatus->value.integer = exit_status;
-         }
+         ourstatus->set_exited (exit_status);
        else
-         {
-           ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
-           ourstatus->value.sig = gdb_signal_from_host (exit_signal);
-         }
+         ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
       }
       child_continue (DBG_CONTINUE, desired_stop_thread_id);
       break;
@@ -1454,10 +1206,9 @@ get_child_debug_event (DWORD *continue_status,
       CloseHandle (current_event.u.LoadDll.hFile);
       if (! child_initialization_done)
        break;
-      handle_load_dll ();
+      dll_loaded_event ();
 
-      ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
+      ourstatus->set_loaded ();
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -1468,8 +1219,7 @@ get_child_debug_event (DWORD *continue_status,
       if (! child_initialization_done)
        break;
       handle_unload_dll ();
-      ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
+      ourstatus->set_loaded ();
       break;
 
     case EXCEPTION_DEBUG_EVENT:
@@ -1511,10 +1261,10 @@ get_child_debug_event (DWORD *continue_status,
                ptid.lwp (), desired_stop_thread_id));
       maybe_adjust_pc ();
       pending_stops.push_back ({(DWORD) ptid.lwp (), *ourstatus, current_event});
-      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+      ourstatus->set_spurious ();
     }
   else
-    current_thread = find_thread_ptid (ptid);
+    switch_to_thread (find_thread_ptid (ptid));
 
   return 1;
 }
@@ -1526,14 +1276,14 @@ ptid_t
 win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
                            target_wait_flags options)
 {
-  if (cached_status.kind != TARGET_WAITKIND_IGNORE)
+  if (cached_status.kind () != TARGET_WAITKIND_IGNORE)
     {
       /* The core always does a wait after creating the inferior, and
         do_initial_child_stuff already ran the inferior to the
         initial breakpoint (or an exit, if creating the process
         fails).  Report it now.  */
       *ourstatus = cached_status;
-      cached_status.kind = TARGET_WAITKIND_IGNORE;
+      cached_status.set_ignore ();
       return debug_event_ptid (&current_event);
     }
 
@@ -1543,11 +1293,11 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
       if (!get_child_debug_event (&continue_status, ourstatus))
        continue;
 
-      switch (ourstatus->kind)
+      switch (ourstatus->kind ())
        {
        case TARGET_WAITKIND_EXITED:
          OUTMSG2 (("Child exited with retcode = %x\n",
-                   ourstatus->value.integer));
+                   ourstatus->exit_status ()));
          win32_clear_inferiors ();
          return ptid_t (current_event.dwProcessId);
        case TARGET_WAITKIND_STOPPED:
@@ -1555,12 +1305,13 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
        case TARGET_WAITKIND_LOADED:
          {
            OUTMSG2 (("Child Stopped with signal = %d \n",
-                     ourstatus->value.sig));
+                     ourstatus->sig ()));
            maybe_adjust_pc ();
            return debug_event_ptid (&current_event);
          }
        default:
-         OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
+         OUTMSG (("Ignoring unknown internal event, %d\n",
+                 ourstatus->kind ()));
          /* fall-through */
        case TARGET_WAITKIND_SPURIOUS:
          /* do nothing, just continue */
@@ -1611,15 +1362,7 @@ win32_process_target::write_memory (CORE_ADDR memaddr,
 void
 win32_process_target::request_interrupt ()
 {
-  winapi_DebugBreakProcess DebugBreakProcess;
-  winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
-
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-
-  GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
-
-  if (GenerateConsoleCtrlEvent != NULL
-      && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
+  if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
     return;
 
   /* GenerateConsoleCtrlEvent can fail if process id being debugged is
@@ -1627,10 +1370,7 @@ win32_process_target::request_interrupt ()
      Fallback to XP/Vista 'DebugBreakProcess', which generates a
      breakpoint exception in the interior process.  */
 
-  DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
-
-  if (DebugBreakProcess != NULL
-      && DebugBreakProcess (current_process_handle))
+  if (DebugBreakProcess (current_process_handle))
     return;
 
   /* Last resort, suspend all threads manually.  */
@@ -1761,11 +1501,5 @@ initialize_low (void)
   set_target_ops (&the_win32_target);
   the_low_target.arch_setup ();
 
-#ifdef __x86_64__
-  /* These functions are loaded dynamically, because they are not available
-     on Windows XP.  */
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  win32_Wow64GetThreadContext = GETPROCADDRESS (dll, Wow64GetThreadContext);
-  win32_Wow64SetThreadContext = GETPROCADDRESS (dll, Wow64SetThreadContext);
-#endif
+  initialize_loadable ();
 }