Mirror of the gdb mailing list
 help / color / mirror / Atom feed
From: Joel Brobecker <brobecker@adacore.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: Kai.Tietz@onevision.com, gdb@sourceware.org
Subject: Re: Support of gdb for Windows 64 native systems
Date: Sat, 13 Oct 2007 02:41:00 -0000	[thread overview]
Message-ID: <20071013024116.GB29152@adacore.com> (raw)
In-Reply-To: <20071012222842.GD21800@adacore.com>

[-- Attachment #1: Type: text/plain, Size: 2592 bytes --]

Hello Eli,

I was able to get rid of i386-win32-tdep.c and use i386-cygwin-tdep.c
instead. So one more difference gone. I fixed the problem with
including <sys/procfs.h> trivially, since we already check for
this include file during the configure phase. The size of the
patch has reduced quite a bit thanks to our discussing this together.

I'm attaching a rough sketch of the changes I think are needed
to adapt the cygwin port to also support mingw. It turns out
that there are more changes that I was claiming. My approach
of serching for ifdefs was a bit over simplistic. Since we have
copyright assignment issues anyway, I haven't tried to be extremely
precise in the patch, as I can't officially submit it for inclusion.
However, this gives a rough idea of the magnitude of the task.

Please ignore the TO_HOST_DIR_SPEC etc changes. These are relics
from the times when we used to provide a cygwin debugger that
pretended to be mingw debugger by outputing/accepting mingw paths.
We should really clean these out of our tree someday...

Back when I worked on this, my approach was to patch only the
files that I thought needed to be patched, rather than importing
the entire mega patch. However, I did tend to apply blindly
the pieces I took, so I don't necessarily know that all the
changes in win32-nat.c are necessary. That's a cleanup left
for later.

I haven't included the configure.tgt change, since it is trivial.
I might be missing some configure.ac changes, I'm not sure.

Here is the mingw.mt makefile fragment:

    # Target: Intel x86 running Win32 (MinGW)
    TDEPFILES= i386-tdep.o i386-cygwin-tdep.o i387-tdep.o solib-target.o
    DEPRECATED_TM_FILE= tm-mingw32.h
    GDBSERVER_DEPFILES=

Unfortunately, as you can see, we're still using a tm file, which
only contains the following definition:

    #define ATTACH_NO_WAIT

It should be pretty easy to work around this. It's strange that
mingw would require it and not cygwin, but I haven't looked deaper
into this. Perhaps cygwin does some magic to fake an event.
It just happens that I had to do the same in my wait loop on
my WTX backend (for VxWorks).

> > >     #ifdef __MINGW32__
> > >       #define MAXPATHLEN PATH_MAX
> > >     #endif
> > 
> > This, for example, is strictly speaking wrong on Windows: Windows
> > supports much longer file names (up to 32K), if you use Unicode APIs.
> 
> You are probably correct, I really know very little about Windows.

This, I still haven't fixed, because I don't know what the proper
thing to do is. What do you think I should use on Windows? I'll
happily fix it.

-- 
Joel

[-- Attachment #2: mingw.diff --]
[-- Type: text/plain, Size: 15359 bytes --]

Index: win32-nat.c
===================================================================
--- win32-nat.c	(.../branches/gdb/FSF/current/gdb)	(revision 15044)
+++ win32-nat.c	(.../trunk/gdb/gdb-head/gdb)	(revision 15044)
@@ -22,8 +22,6 @@
 
 /* Originally by Steve Chamberlain, sac@cygnus.com */
 
-/* We assume we're being built with and will be used for cygwin.  */
-
 #include "defs.h"
 #include "frame.h"		/* required by inferior.h */
 #include "inferior.h"
@@ -40,7 +38,9 @@
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#ifdef HAVE_SYS_CYGWIN_H
 #include <sys/cygwin.h>
+#endif
 #include <signal.h>
 
 #include "buildsym.h"
@@ -51,6 +51,9 @@
 #include "gdbthread.h"
 #include "gdbcmd.h"
 #include <sys/param.h>
+#ifdef __MINGW32__
+  #define MAXPATHLEN PATH_MAX
+#endif
 #include <unistd.h>
 #include "exec.h"
 #include "solist.h"
@@ -81,7 +84,9 @@ enum
     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
   };
 #endif
+#ifdef HAVE_SYS_PROCFS_H
 #include <sys/procfs.h>
+#endif
 #include <psapi.h>
 
 #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
@@ -105,6 +110,7 @@ static int debug_registers_used;
 
 static void win32_stop (void);
 static int win32_win32_thread_alive (ptid_t);
+static char *win32_pid_to_str (ptid_t ptid);
 static void win32_kill_inferior (void);
 
 static enum target_signal last_sig = TARGET_SIGNAL_0;
@@ -237,10 +243,52 @@ static void
 check (BOOL ok, const char *file, int line)
 {
   if (!ok)
-    printf_filtered ("error return %s:%d was %lu\n", file, line,
-		     GetLastError ());
+  {
+    LPVOID lpMsgBuf;
+    DWORD  last_error = GetLastError ();
+    if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+                       FORMAT_MESSAGE_FROM_SYSTEM | 
+                       FORMAT_MESSAGE_IGNORE_INSERTS,
+                       NULL,
+                       last_error,
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR) &lpMsgBuf,
+                       0,
+                       NULL))
+    {
+      printf_filtered ("error return %s:%d was %lu\n", file, line,
+                       last_error);
+    }
+    else
+    {
+      printf_filtered ("error return %s:%d: [%lu] %s\n", file, line,
+                       last_error, (LPCTSTR) lpMsgBuf);
+      LocalFree (lpMsgBuf);
+    }
+  }
 }
 
+#ifndef HAVE_CYGWIN_CONV_TO_POSIX_PATH
+/* A basic replacement implementation for cygwin_conv_to_posix_path ()
+   when not available (basically, when building using a MinGW compiler).  */
+
+static void
+cygwin_conv_to_posix_path (const char *path, char *posix_path)
+{
+  strcpy (posix_path, path);
+}
+#endif
+
+#ifndef HAVE_CYGWIN_CONV_TO_WIN32_PATH
+/* A basic replacement implementation for cygwin_conv_to_win32_path ()
+   when not available (basically, when building using a MinGW compiler).  */
+static void
+cygwin_conv_to_win32_path (const char *path, char *win32_path)
+{
+  strcpy (win32_path, path);
+}
+#endif
+
 /* Find a thread record given a thread id.
    If get_context then also retrieve the context for this
    thread. */
@@ -446,30 +494,22 @@ static BOOL WINAPI (*psapi_EnumProcessMo
 static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
 static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
 
-static int
-psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+BOOL
+load_psapi ()
 {
-  DWORD len;
-  MODULEINFO mi;
-  int i;
-  HMODULE dh_buf[1];
-  HMODULE *DllHandle = dh_buf;
-  DWORD cbNeeded;
-  BOOL ok;
-
   if (!psapi_loaded ||
       psapi_EnumProcessModules == NULL ||
       psapi_GetModuleInformation == NULL ||
       psapi_GetModuleFileNameExA == NULL)
     {
       if (psapi_loaded)
-	goto failed;
+	return FALSE;
       psapi_loaded = 1;
       psapi_module_handle = LoadLibrary ("psapi.dll");
       if (!psapi_module_handle)
 	{
 	  /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
-	  goto failed;
+	  return FALSE;
 	}
       psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
       psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
@@ -478,9 +518,25 @@ psapi_get_dll_name (DWORD BaseAddress, c
       if (psapi_EnumProcessModules == NULL ||
 	  psapi_GetModuleInformation == NULL ||
 	  psapi_GetModuleFileNameExA == NULL)
-	goto failed;
+	    return FALSE;
     }
+  return TRUE;
+}
 
+int
+psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+{
+  DWORD len;
+  MODULEINFO mi;
+  int i;
+  HMODULE dh_buf[1];
+  HMODULE *DllHandle = dh_buf;
+  DWORD cbNeeded;
+  BOOL ok;
+
+  if (!load_psapi ())
+    goto failed;
+  
   cbNeeded = 0;
   ok = (*psapi_EnumProcessModules) (current_process_handle,
 				    DllHandle,
@@ -525,6 +581,29 @@ failed:
   return 0;
 }
 
+int
+psapi_get_module_filename (HANDLE hProcess,
+                           HMODULE hModule,
+                           LPTSTR lpFilename,
+                           DWORD nSize)
+{
+  DWORD len;
+
+  if (!load_psapi ())
+    goto failed;
+  
+  len = (*psapi_GetModuleFileNameExA) (hProcess,
+                                       hModule,
+                                       lpFilename,
+                                       nSize);
+  if (len == 0)
+    error ("Error getting file name: %u\n", (unsigned) GetLastError ());
+
+failed:
+  lpFilename[0] = '\0';
+  return 0;
+}
+
 /* Encapsulate the information required in a call to
    symbol_file_add_args */
 struct safe_symbol_file_add_args
@@ -542,6 +621,9 @@ struct safe_symbol_file_add_args
 struct lm_info
 {
   DWORD load_addr;
+
+  /* The ImageBase, aka the prefered load address.  */
+  CORE_ADDR image_base;
 };
 
 static struct so_list solib_start, *solib_end;
@@ -637,6 +719,7 @@ win32_make_so (const char *name, DWORD l
   so = XZALLOC (struct so_list);
   so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
   so->lm_info->load_addr = load_addr;
+  so->lm_info->image_base = 0; /* Will be filled in later.  */
   cygwin_conv_to_posix_path (buf, so->so_name);
   strcpy (so->so_original_name, name);
 
@@ -769,7 +852,14 @@ handle_unload_dll (void *dummy)
 	return 1;
       }
 
-  error (_("Error: dll starting at 0x%lx not found."), (DWORD) lpBaseOfDll);
+  /* brobecker/2006-06-15: If we reach that point, that means that
+     the debugger doesn't know of any DLL loaded at this particular
+     address.  The reason for this discrepancy is unknown, but what
+     we have found out is that all the users have found an error
+     message to be confusing, and useless (no real information as
+     to what is happening such as the DLL name for instance can be
+     computed).  In any case, it's just fine to ignore this unload
+     event and continue silently.  */
 
   return 0;
 }
@@ -1227,6 +1317,10 @@ win32_resume (ptid_t ptid, int step, enu
 	       FIXME: should we set dr6 also ?? */
 	      th->context.Dr7 = dr[7];
 	    }
+	  
+	  DEBUG_EVENTS (("gdb: child_resume.SetThreadContext: %s\n",
+			 target_pid_to_str (pid_to_ptid (th->id))));
+  
 	  CHECK (SetThreadContext (th->h, &th->context));
 	  th->context.ContextFlags = 0;
 	}
@@ -1465,6 +1559,9 @@ do_initial_win32_stuff (DWORD pid)
   extern int stop_after_trap;
   int i;
 
+  DEBUG_EVENTS (("gdb: do_initial_child_stuff: %s\n",
+                 target_pid_to_str (pid_to_ptid (pid))));
+  
   last_sig = TARGET_SIGNAL_0;
   event_count = 0;
   exception_count = 0;
@@ -1627,6 +1724,10 @@ win32_attach (char *args, int from_tty)
 
   if (!ok)
     {
+#ifdef __CYGWIN__
+      /* FIXME: This can be implemented better.  Just moved the last
+         if (!ok) block out of this if block, and put this entire
+         if block under #ifdef __CYGWIN__.  */
       /* Try fall back to Cygwin pid */
       pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
 
@@ -1634,6 +1735,7 @@ win32_attach (char *args, int from_tty)
 	ok = DebugActiveProcess (pid);
 
       if (!ok)
+#endif /* __CYGWIN__ */
 	error (_("Can't attach to process."));
     }
 
@@ -1694,13 +1796,14 @@ win32_detach (char *args, int from_tty)
 static char *
 win32_pid_to_exec_file (int pid)
 {
+  static char path[MAX_PATH + 1];
+  char *path_ptr = NULL;
+#ifdef __CYGWIN__
   /* Try to find the process path using the Cygwin internal process list
      pid isn't a valid pid, unfortunately.  Use current_event.dwProcessId
      instead.  */
   /* TODO: Also find native Windows processes using CW_GETPINFO_FULL.  */
 
-  static char path[MAX_PATH + 1];
-  char *path_ptr = NULL;
   int cpid;
   struct external_pinfo *pinfo;
 
@@ -1718,7 +1821,15 @@ win32_pid_to_exec_file (int pid)
        }
     }
   cygwin_internal (CW_UNLOCK_PINFO);
+#else
+  if (!psapi_get_module_filename (current_process_handle, NULL, path, MAX_PATH))
+    printf_unfiltered ("error reading the process's file name: %lu",
+                       GetLastError ());
+  else
+    path_ptr = path;
+#endif
   return path_ptr;
+
 }
 
 /* Print status information about what we're accessing.  */
@@ -1736,6 +1847,15 @@ win32_open (char *arg, int from_tty)
   error (_("Use the \"run\" command to start a Unix child process."));
 }
 
+/* Function called by qsort to sort environment strings.  */
+static int
+env_sort (const void *a, const void *b)
+{
+  const char **p = (const char **) a;
+  const char **q = (const char **) b;
+  return strcasecmp (*p, *q);
+}
+
 /* Start an inferior win32 child process and sets inferior_ptid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
@@ -1754,8 +1874,16 @@ win32_create_inferior (char *exec_file, 
   char *toexec;
   char shell[MAX_PATH + 1]; /* Path to shell */
   const char *sh;
+#if defined (__MINGW32__)
+  /* BEGIN: Fragment of Al Stevens's patch for GDB on Win9x */
+  HANDLE hStdInput = 0;
+  HANDLE hStdOutput = 0;
+  HANDLE hStdError = 0;
+  /* END: Fragment of Al Stevens's patch for GDB on Win9x */
+#else /* !__MINGW32__ */
   int tty;
   int ostdin, ostdout, ostderr;
+#endif /* !__MINGW32__ */
   const char *inferior_io_terminal = get_inferior_io_terminal ();
 
   if (!exec_file)
@@ -1799,8 +1927,90 @@ win32_create_inferior (char *exec_file, 
   strcat (args, allargs);
 
   /* Prepare the environment vars for CreateProcess.  */
+#ifdef __CYGWIN__
   cygwin_internal (CW_SYNC_WINENV);
+#else
+ {
+    static const char *conv_path_names[] =
+    {
+      "PATH=",
+      0
+    };
+    int envlen;
+    int i;
+    size_t envsize;
+    char **env;
+    char *winenv;
+    char *temp;
+
+    /* CreateProcess takes the environment list as a null terminated set of
+       strings (i.e. two nulls terminate the list).  */
+
+    /* Get total size for env strings.  */
+    for (envlen = 0, i = 0; in_env[i] && *in_env[i]; i++)
+      {
+	int j, len;
+
+	for (j = 0; conv_path_names[j]; j++)
+	  {
+	    len = strlen (conv_path_names[j]);
+	    if (strncmp (conv_path_names[j], in_env[i], len) == 0)
+	      {
+		envlen += strlen (in_env[i]) + 1;
+		break;
+	      }
+	  }
+	if (conv_path_names[j] == NULL)
+	  envlen += strlen (in_env[i]) + 1;
+      }
+
+    envsize = sizeof (in_env[0]) * (i + 1);
+    env = (char **) alloca (envsize);
+    memcpy (env, in_env, envsize);
+    /* Windows programs expect the environment block to be sorted.  */
+    qsort (env, i, sizeof (char *), env_sort);
+
+    winenv = alloca (envlen + 1);
+
+    /* Copy env strings into new buffer.  */
+    for (temp = winenv, i = 0; env[i] && *env[i]; i++)
+      {
+	int j, len;
+
+	for (j = 0; conv_path_names[j]; j++)
+	  {
+	    len = strlen (conv_path_names[j]);
+	    if (strncmp (conv_path_names[j], env[i], len) == 0)
+	      {
+		strcpy (temp, env[i]);
+		break;
+	      }
+	  }
+	if (conv_path_names[j] == NULL)
+	  strcpy (temp, env[i]);
 
+	temp += strlen (temp) + 1;
+      }
+
+    /* Final nil string to terminate new env.  */
+    *temp = 0;
+ }
+#endif
+
+#if defined (__MINGW32__)
+  /* BEGIN: Fragment of Al Stevens's patch for GDB on Win9x */
+  if ( new_console)
+    {
+      hStdInput = GetStdHandle( STD_INPUT_HANDLE);
+      hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE);
+      hStdError = GetStdHandle( STD_ERROR_HANDLE);
+
+      SetStdHandle( STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
+      SetStdHandle( STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
+      SetStdHandle( STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
+    }
+  /* END: Fragment of Al Stevens's patch for GDB on Win9x */
+#else /* !__MINGW32__ */
   if (!inferior_io_terminal)
     tty = ostdin = ostdout = ostderr = -1;
   else
@@ -1821,6 +2031,7 @@ win32_create_inferior (char *exec_file, 
 	  dup2 (tty, 2);
 	}
     }
+#endif /* !__MINGW32__ */
 
   win32_init_thread_list ();
   ret = CreateProcess (0,
@@ -1833,6 +2044,16 @@ win32_create_inferior (char *exec_file, 
 		       NULL,	/* current directory */
 		       &si,
 		       &pi);
+#if defined (__MINGW32__)
+  /* BEGIN: Fragment of Al Stevens's patch for GDB on Win9x */
+  if ( new_console)
+    {
+      SetStdHandle( STD_INPUT_HANDLE, hStdInput);
+      SetStdHandle( STD_OUTPUT_HANDLE, hStdOutput);
+      SetStdHandle( STD_ERROR_HANDLE, hStdError);
+    }
+  /* END: Fragment of Al Stevens's patch for GDB on Win9x */
+#else /* !__MINGW32__ */
   if (tty >= 0)
     {
       close (tty);
@@ -1843,7 +2064,7 @@ win32_create_inferior (char *exec_file, 
       close (ostdout);
       close (ostderr);
     }
-
+#endif /* !__MINGW32__ */
   if (!ret)
     error (_("Error creating process %s, (error %d)."),
 	   exec_file, (unsigned) GetLastError ());
@@ -1947,11 +2168,15 @@ win32_close (int x)
 {
   DEBUG_EVENTS (("gdb: win32_close, inferior_ptid=%d\n",
 		PIDGET (inferior_ptid)));
+  win32_init_thread_list ();
+  disable_breakpoints_in_shlibs ();
+  win32_clear_solib ();
+  clear_proceed_status ();
 }
 
 /* Convert pid to printable format. */
 static char *
-cygwin_pid_to_str (ptid_t ptid)
+win32_pid_to_str (ptid_t ptid)
 {
   static char buf[80];
   int pid = PIDGET (ptid);
@@ -2055,7 +2280,7 @@ init_win32_ops (void)
   win32_ops.to_mourn_inferior = win32_mourn_inferior;
   win32_ops.to_can_run = win32_can_run;
   win32_ops.to_thread_alive = win32_win32_thread_alive;
-  win32_ops.to_pid_to_str = cygwin_pid_to_str;
+  win32_ops.to_pid_to_str = win32_pid_to_str;
   win32_ops.to_stop = win32_stop;
   win32_ops.to_stratum = process_stratum;
   win32_ops.to_has_all_memory = 1;
Index: symfile.c
===================================================================
--- symfile.c	(.../branches/gdb/FSF/current/gdb)	(revision 15044)
+++ symfile.c	(.../trunk/gdb/gdb-head/gdb)	(revision 15044)
@@ -1641,10 +1674,21 @@ symfile_bfd_open (char *name)
     {
       close (desc);
       make_cleanup (xfree, name);
-      error (_("\"%s\": can't open to read symbols: %s."), name,
+      error (_("\"%s\": can't open to read symbols: %s."), 
+	     TO_HOST_FILE_SPEC (name),
 	     bfd_errmsg (bfd_get_error ()));
     }
-  bfd_set_cacheable (sym_bfd, 1);
+
+#ifdef _WIN32
+  /* The executable must not be closed because it will not been possible to
+     reopen it later under Windows NT if this executable is the one being
+     debugged. */
+
+  if (strstr (name, ".exe") != NULL)
+    sym_bfd->cacheable = FALSE;
+  else
+#endif
+    bfd_set_cacheable (sym_bfd, 1);
 
   if (!bfd_check_format (sym_bfd, bfd_object))
     {

  reply	other threads:[~2007-10-13  2:41 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20071011142348.GA18239@caradoc.them.org>
2007-10-11 14:47 ` Kai Tietz
     [not found]   ` <20071011145549.GA19918@caradoc.them.org>
2007-10-11 16:01     ` Joel Brobecker
2007-10-12  3:38       ` Christopher Faylor
2007-10-12  4:27         ` Joel Brobecker
2007-10-11 16:37     ` Mark Kettenis
2007-10-12  7:19     ` Kai Tietz
2007-10-12  8:44     ` Eli Zaretskii
2007-10-12 16:11       ` Joel Brobecker
2007-10-12 16:51         ` Eli Zaretskii
2007-10-12 17:45           ` Joel Brobecker
2007-10-12 20:29             ` Eli Zaretskii
2007-10-12 22:28               ` Joel Brobecker
2007-10-13  2:41                 ` Joel Brobecker [this message]
2007-10-13 10:48                   ` Eli Zaretskii
2007-10-13 15:47                     ` Joel Brobecker
2007-10-13 17:05                       ` Christopher Faylor
2007-10-13 17:36                       ` Pedro Alves
2007-10-13 19:09                         ` Eli Zaretskii
2007-10-13 19:19                           ` Pedro Alves
2007-10-13 20:51                         ` Joel Brobecker
2007-10-13 22:52                           ` Pedro Alves
2007-10-14  5:16                             ` Joel Brobecker
2007-10-14 11:44                               ` Pedro Alves
2007-10-14 20:33                                 ` Eli Zaretskii
2007-10-12 17:38         ` Pedro Alves
2007-10-11 13:53 Kai Tietz
2007-10-11 14:05 ` Daniel Jacobowitz
2007-10-11 14:18   ` Kai Tietz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071013024116.GB29152@adacore.com \
    --to=brobecker@adacore.com \
    --cc=Kai.Tietz@onevision.com \
    --cc=eliz@gnu.org \
    --cc=gdb@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox