2009-07-01 Tristan Gingold <gingold@adacore.com>
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index e80c4c56da002c51e351f75d401c2c08f36fc3e1..2fa79af65804156a7a7d8c7f79569187ebb86b5a 100644 (file)
 
 #include "windows-tdep.h"
 #include "windows-nat.h"
+#include "i386-nat.h"
 
+#define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop         dyn_DebugActiveProcessStop
 #define DebugBreakProcess              dyn_DebugBreakProcess
 #define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
 #define EnumProcessModules             dyn_EnumProcessModules
 #define GetModuleFileNameExA           dyn_GetModuleFileNameExA
 #define GetModuleInformation           dyn_GetModuleInformation
+#define LookupPrivilegeValueA          dyn_LookupPrivilegeValueA
+#define OpenProcessToken               dyn_OpenProcessToken
 
-/* Since Windows XP, detaching from a process is supported by Windows.
-   The following code tries loading the appropriate functions dynamically.
-   If loading these functions succeeds use them to actually detach from
-   the inferior process, otherwise behave as usual, pretending that
-   detach has worked. */
+static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
+                                           DWORD, PTOKEN_PRIVILEGES, PDWORD);
 static BOOL WINAPI (*DebugActiveProcessStop) (DWORD);
 static BOOL WINAPI (*DebugBreakProcess) (HANDLE);
 static BOOL WINAPI (*DebugSetProcessKillOnExit) (BOOL);
@@ -85,6 +86,8 @@ static DWORD WINAPI (*GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
                                            DWORD);
 static BOOL WINAPI (*GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
                                            DWORD);
+static BOOL WINAPI (*LookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
+static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
 
 static struct target_ops windows_ops;
 
@@ -138,6 +141,10 @@ static void windows_stop (ptid_t);
 static int windows_thread_alive (struct target_ops *, ptid_t);
 static void windows_kill_inferior (struct target_ops *);
 
+static void cygwin_set_dr (int i, CORE_ADDR addr);
+static void cygwin_set_dr7 (unsigned long val);
+static unsigned long cygwin_get_dr6 (void);
+
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 /* Set if a signal was received from the debugged process */
 
@@ -549,7 +556,9 @@ static int
 safe_symbol_file_add_stub (void *argv)
 {
 #define p ((struct safe_symbol_file_add_args *) argv)
-  p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
+  const int add_flags = ((p->from_tty ? SYMFILE_VERBOSE : 0)
+                         | (p->mainline ? SYMFILE_MAINLINE : 0));
+  p->ret = symbol_file_add (p->name, add_flags, p->addrs, p->flags);
   return !!p->ret;
 #undef p
 }
@@ -738,8 +747,8 @@ handle_load_dll (void *dummy)
   solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
   solib_end = solib_end->next;
 
-  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %p.\n", solib_end->so_name,
-                solib_end->lm_info->load_addr));
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
+                host_address_to_string (solib_end->lm_info->load_addr)));
 
   return 1;
 }
@@ -772,7 +781,8 @@ handle_unload_dll (void *dummy)
        return 1;
       }
 
-  error (_("Error: dll starting at %p not found."), lpBaseOfDll);
+  error (_("Error: dll starting at %s not found."),
+          host_address_to_string (lpBaseOfDll));
 
   return 0;
 }
@@ -984,8 +994,9 @@ info_w32_command (char *args, int from_tty)
 
 
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
-  printf_unfiltered ("gdb: Target exception %s at %p\n", x, \
-                    current_event.u.Exception.ExceptionRecord.ExceptionAddress)
+  printf_unfiltered ("gdb: Target exception %s at %s\n", x, \
+    host_address_to_string (\
+      current_event.u.Exception.ExceptionRecord.ExceptionAddress))
 
 static int
 handle_exception (struct target_waitstatus *ourstatus)
@@ -1096,9 +1107,10 @@ handle_exception (struct target_waitstatus *ourstatus)
       /* Treat unhandled first chance exceptions specially. */
       if (current_event.u.Exception.dwFirstChance)
        return -1;
-      printf_unfiltered ("gdb: unknown target exception 0x%08lx at %p\n",
-                   current_event.u.Exception.ExceptionRecord.ExceptionCode,
-                   current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+      printf_unfiltered ("gdb: unknown target exception 0x%08lx at %s\n",
+       current_event.u.Exception.ExceptionRecord.ExceptionCode,
+       host_address_to_string (
+         current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       break;
     }
@@ -1236,9 +1248,10 @@ windows_resume (struct target_ops *ops,
       if (step)
        {
          /* Single step by setting t bit */
-         windows_fetch_inferior_registers (ops,
-                                           get_current_regcache (),
-                                           gdbarch_ps_regnum (current_gdbarch));
+         struct regcache *regcache = get_current_regcache ();
+         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         windows_fetch_inferior_registers (ops, regcache,
+                                           gdbarch_ps_regnum (gdbarch));
          th->context.EFlags |= FLAG_TRACE_BIT;
        }
 
@@ -1267,9 +1280,34 @@ windows_resume (struct target_ops *ops,
     windows_continue (continue_status, ptid_get_tid (ptid));
 }
 
+/* Ctrl-C handler used when the inferior is not run in the same console.  The
+   handler is in charge of interrupting the inferior using DebugBreakProcess.
+   Note that this function is not available prior to Windows XP.  In this case
+   we emit a warning.  */
+BOOL WINAPI
+ctrl_c_handler (DWORD event_type)
+{
+  const int attach_flag = current_inferior ()->attach_flag;
+
+  /* Only handle Ctrl-C event.  Ignore others.  */
+  if (event_type != CTRL_C_EVENT)
+    return FALSE;
+
+  /* If the inferior and the debugger share the same console, do nothing as
+     the inferior has also received the Ctrl-C event.  */
+  if (!new_console && !attach_flag)
+    return TRUE;
+
+  if (!DebugBreakProcess (current_process_handle))
+    warning (_("\
+Could not interrupt program.  Press Ctrl-c in the program console."));
+
+  /* Return true to tell that Ctrl-C has been handled.  */
+  return TRUE;
+}
+
 /* Get the next event from the child.  Return 1 if the event requires
-   handling by WFI (or whatever).
- */
+   handling by WFI (or whatever).  */
 static int
 get_windows_debug_event (struct target_ops *ops,
                         int pid, struct target_waitstatus *ourstatus)
@@ -1346,13 +1384,13 @@ get_windows_debug_event (struct target_ops *ops,
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       if (main_thread_id)
-       windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
-                                        main_thread_id));
+       windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          main_thread_id));
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread */
       th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
-                                        current_event.dwThreadId),
-                            current_event.u.CreateProcessInfo.hThread);
+                                          current_event.dwThreadId),
+                              current_event.u.CreateProcessInfo.hThread);
       retval = current_event.dwThreadId;
       break;
 
@@ -1459,7 +1497,7 @@ out:
 /* Wait for interesting events to occur in the target process.  */
 static ptid_t
 windows_wait (struct target_ops *ops,
-             ptid_t ptid, struct target_waitstatus *ourstatus)
+             ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
   int pid = -1;
 
@@ -1475,22 +1513,35 @@ windows_wait (struct target_ops *ops,
     {
       int retval;
 
-      /* Ignore CTRL+C signals while waiting for a debug event.
-        FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
-        the inferior is running, both the inferior and GDB receive the
-        associated signal.  If the inferior receives the signal first
-        and the delay until GDB receives that signal is sufficiently long,
-        GDB can sometimes receive the SIGINT after we have unblocked
-        the CTRL+C handler.  This would lead to the debugger to stop
-        prematurely while handling the new-thread event that comes
-        with the handling of the SIGINT inside the inferior, and then
-        stop again immediately when the user tries to resume the execution
-        in the inferior.  This is a classic race, and it would be nice
-        to find a better solution to that problem.  But in the meantime,
-        the current approach already greatly mitigate this issue.  */
-      SetConsoleCtrlHandler (NULL, TRUE);
+      /* If the user presses Ctrl-c while the debugger is waiting
+        for an event, he expects the debugger to interrupt his program
+        and to get the prompt back.  There are two possible situations:
+
+          - The debugger and the program do not share the console, in
+            which case the Ctrl-c event only reached the debugger.
+            In that case, the ctrl_c handler will take care of interrupting
+            the inferior. Note that this case is working starting with
+            Windows XP. For Windows 2000, Ctrl-C should be pressed in the
+            inferior console.
+
+          - The debugger and the program share the same console, in which
+            case both debugger and inferior will receive the Ctrl-c event.
+            In that case the ctrl_c handler will ignore the event, as the
+            Ctrl-c event generated inside the inferior will trigger the
+            expected debug event.
+
+            FIXME: brobecker/2008-05-20: If the inferior receives the
+            signal first and the delay until GDB receives that signal
+            is sufficiently long, GDB can sometimes receive the SIGINT
+            after we have unblocked the CTRL+C handler.  This would
+            lead to the debugger stopping prematurely while handling
+            the new-thread event that comes with the handling of the SIGINT
+            inside the inferior, and then stop again immediately when
+            the user tries to resume the execution in the inferior.
+            This is a classic race that we should try to fix one day.  */
+      SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
       retval = get_windows_debug_event (ops, pid, ourstatus);
-      SetConsoleCtrlHandler (NULL, FALSE);
+      SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
 
       if (retval)
        return ptid_build (current_event.dwProcessId, 0, retval);
@@ -1572,47 +1623,18 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 static int
 set_process_privilege (const char *privilege, BOOL enable)
 {
-  static HMODULE advapi32 = NULL;
-  static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
-  static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
-  static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
-                                             DWORD, PTOKEN_PRIVILEGES, PDWORD);
-
   HANDLE token_hdl = NULL;
   LUID restore_priv;
   TOKEN_PRIVILEGES new_priv, orig_priv;
   int ret = -1;
   DWORD size;
 
-  if (GetVersion () >= 0x80000000)  /* No security availbale on 9x/Me */
-    return 0;
-
-  if (!advapi32)
-    {
-      if (!(advapi32 = LoadLibrary ("advapi32.dll")))
-       goto out;
-      if (!OpenProcessToken)
-       OpenProcessToken =
-         (void *) GetProcAddress (advapi32, "OpenProcessToken");
-      if (!LookupPrivilegeValue)
-       LookupPrivilegeValue =
-         (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA");
-      if (!AdjustTokenPrivileges)
-       AdjustTokenPrivileges =
-         (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges");
-      if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
-       {
-         advapi32 = NULL;
-         goto out;
-       }
-    }
-
   if (!OpenProcessToken (GetCurrentProcess (),
                         TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
                         &token_hdl))
     goto out;
 
-  if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
+  if (!LookupPrivilegeValueA (NULL, privilege, &restore_priv))
     goto out;
 
   new_priv.PrivilegeCount = 1;
@@ -2104,6 +2126,12 @@ windows_xfer_partial (struct target_ops *ops, enum target_object object,
     }
 }
 
+static ptid_t
+windows_get_ada_task_ptid (long lwp, long thread)
+{
+  return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
+}
+
 static void
 init_windows_ops (void)
 {
@@ -2139,14 +2167,25 @@ init_windows_ops (void)
   windows_ops.to_pid_to_str = windows_pid_to_str;
   windows_ops.to_stop = windows_stop;
   windows_ops.to_stratum = process_stratum;
-  windows_ops.to_has_all_memory = 1;
-  windows_ops.to_has_memory = 1;
-  windows_ops.to_has_stack = 1;
-  windows_ops.to_has_registers = 1;
-  windows_ops.to_has_execution = 1;
+  windows_ops.to_has_all_memory = default_child_has_all_memory;
+  windows_ops.to_has_memory = default_child_has_memory;
+  windows_ops.to_has_stack = default_child_has_stack;
+  windows_ops.to_has_registers = default_child_has_registers;
+  windows_ops.to_has_execution = default_child_has_execution;
   windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
+  windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
+
   i386_use_watchpoints (&windows_ops);
 
+  i386_dr_low.set_control = cygwin_set_dr7;
+  i386_dr_low.set_addr = cygwin_set_dr;
+  i386_dr_low.reset_addr = NULL;
+  i386_dr_low.get_status = cygwin_get_dr6;
+
+  /* i386_dr_low.debug_register_length field is set by
+     calling i386_set_debug_register_length function
+     in processor windows specific native file.  */
+
   windows_ops.to_magic = OPS_MAGIC;
 }
 
@@ -2169,6 +2208,10 @@ _initialize_windows_nat (void)
 
   add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
 
+  add_com_alias ("add-shared-symbol-files", "dll-symbols", class_alias, 1);
+
+  add_com_alias ("assf", "dll-symbols", class_alias, 1);
+
 #ifdef __CYGWIN__
   add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\
 Set use of shell to start subprocess."), _("\
@@ -2244,7 +2287,7 @@ Show whether to display kernel exceptions in child process."), NULL,
 /* Pass the address ADDR to the inferior in the I'th debug register.
    Here we just store the address in dr array, the registers will be
    actually set up when windows_continue is called.  */
-void
+static void
 cygwin_set_dr (int i, CORE_ADDR addr)
 {
   if (i < 0 || i > 3)
@@ -2258,10 +2301,10 @@ cygwin_set_dr (int i, CORE_ADDR addr)
 /* Pass the value VAL to the inferior in the DR7 debug control
    register.  Here we just store the address in D_REGS, the watchpoint
    will be actually set up in windows_wait.  */
-void
-cygwin_set_dr7 (unsigned val)
+static void
+cygwin_set_dr7 (unsigned long val)
 {
-  dr[7] = val;
+  dr[7] = (CORE_ADDR) val;
   debug_registers_changed = 1;
   debug_registers_used = 1;
 }
@@ -2269,10 +2312,10 @@ cygwin_set_dr7 (unsigned val)
 /* Get the value of the DR6 debug status register from the inferior.
    Here we just return the value stored in dr[6]
    by the last call to thread_rec for current_event.dwThreadId id.  */
-unsigned
+static unsigned long
 cygwin_get_dr6 (void)
 {
-  return dr[6];
+  return (unsigned long) dr[6];
 }
 
 /* Determine if the thread referenced by "ptid" is alive
@@ -2352,6 +2395,12 @@ bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
   return FALSE;
 }
 
+static BOOL WINAPI
+bad_OpenProcessToken (HANDLE w, DWORD x, PHANDLE y)
+{
+  return FALSE;
+}
+
 /* Load any functions which may not be available in ancient versions
    of Windows. */
 void
@@ -2402,6 +2451,21 @@ _initialize_loadable (void)
       dyn_GetModuleFileNameExA = bad_GetModuleFileNameExA;
       /* This will probably fail on Windows 9x/Me.  Let the user know that we're
         missing some functionality. */
-      warning(_("cannot automatically find executable file or library to read symbols.  Use \"file\" or \"dll\" command to load executable/libraries directly."));
+      warning(_("cannot automatically find executable file or library to read symbols.\nUse \"file\" or \"dll\" command to load executable/libraries directly."));
+    }
+
+  hm = LoadLibrary ("advapi32.dll");
+  if (hm)
+    {
+      dyn_OpenProcessToken = (void *)
+       GetProcAddress (hm, "OpenProcessToken");
+      dyn_LookupPrivilegeValueA = (void *)
+       GetProcAddress (hm, "LookupPrivilegeValueA");
+      dyn_AdjustTokenPrivileges = (void *)
+       GetProcAddress (hm, "AdjustTokenPrivileges");
+      /* Only need to set one of these since if OpenProcessToken fails nothing
+        else is needed. */
+      if (!dyn_OpenProcessToken || !dyn_LookupPrivilegeValueA || !dyn_AdjustTokenPrivileges)
+       dyn_OpenProcessToken = bad_OpenProcessToken;
     }
 }
This page took 0.0318619999999999 seconds and 4 git commands to generate.