[RFA] windows-nat.c: Cygwin: Port to Cygwin 1.7

Corinna Vinschen vinschen@redhat.com
Sun Feb 28 15:09:00 GMT 2010


Hi,

the below patch ports GDB to the latest Cygwin version 1.7.

Three problems have to be fixed:

- The maximum path length in Cygwin is no longer MAX_PATH.  Rather it
  is PATH_MAX, which is now 4096.  Actually, even paths up to 32K are
  supported, which is the maximum path length of the underlying Windows,
  but usually 4K is more than enough.

- The aforementioned change required to provide a new Win32<->POSIX
  path conversion API which allows to handle paths longer than MAX_PATH.
  The old cygwin_conv_to_[full_]win32_path and cygwin_conf_to_[full_]posix
  path functions are deprecated now.  The below patch uses the new
  cygwin_conv_path API instead.

- The Windows ANSI functions have two drawbacks.

  - They return paths always in the default ANSI codepage, which is
    typically not the default codeset used in Cygwin 1.7 anymore.  UTF-8
    is now the default codeset in Cygwin.

  - They are restricted to a path length of MAX_PATH bytes.

  Since UTF-8 support and support for long paths are key changes in
  Cygwin 1.7, Cygwin now uses only Unicode Windows or native NT
  functions internally.  To overcome the restrictions of the Win32 ANSI
  functions in GDB as well, the patch changes the affected calls to use
  the Unicode variation instead, too.

The code for other Win32 targets is unaffected by this patch, except
for a patch in get_image_name.  The WideCharToMultiByte function is
called with an incorrect target buffer size.

Ok to apply?


Thanks,
Corinna


	* remote-fileio.c (remote_fileio_func_rename): Use Cygwin 1.7
	cygwin_conv_path API rather than the deprecated
	cygwin_conv_to_full_posix_path.
	* windows-nat.c:
	(GetModuleFileNameExA): Undefine for Cygwin.
	(GetModuleFileNameExW): Define for Cygwin.
	(get_module_name): Change size of pathbuf to PATH_MAX for Cygwin.
	Call GetModuleFileNameExW and convert path to POSIX using
	cygwin_conv_path.
	(windows_make_so): Always define p.  Drop unused variable m.
	Don't use Win32 functions to check file existance, rather use
	access on Cygwin.  Fetch system directory using GetSystemDirectoryW.
	Use canonicalize_file_name to get full path.
	(get_image_name): Use wcstombs, rather than WideCharToMultiByte
	to convert Unicode pathname to multibyte on Cygwin.  Otherwise,
	use correct target buffer size in call to WideCharToMultiByte.
	(handle_load_dll): Change size of dll_buf to PATH_MAX for Cygwin.
	(windows_pid_to_exec_file): Change size of path to PATH_MAX for Cygwin.
	(windows_create_inferior): Convert all paths and arguments to wchar_t
	and use CreateProcessW on Cygwin.
	(_initialize_windows_nat): Disable DOS-style path warning on Cygwin.
	(bad_GetModuleFileNameExA): Undefine for Cygwin.
	(bad_GetModuleFileNameExW): Define for Cygwin.
	(_initialize_loadable): Load GetModuleFileNameExW into
	dyn_GetModuleFileNameExW on Cygwin.  Don't load ANSI function on Cygwin.


Index: remote-fileio.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-fileio.c,v
retrieving revision 1.33
diff -u -p -r1.33 remote-fileio.c
--- remote-fileio.c	1 Jan 2010 07:31:40 -0000	1.33
+++ remote-fileio.c	28 Feb 2010 15:07:05 -0000
@@ -1021,12 +1021,14 @@ remote_fileio_func_rename (char *buf)
 		errno = EISDIR;
 	      else
 		{
-		  char oldfullpath[PATH_MAX + 1];
-		  char newfullpath[PATH_MAX + 1];
+		  char oldfullpath[PATH_MAX];
+		  char newfullpath[PATH_MAX];
 		  int len;
 
-		  cygwin_conv_to_full_posix_path (oldpath, oldfullpath);
-		  cygwin_conv_to_full_posix_path (newpath, newfullpath);
+		  cygwin_conv_path (CCP_WIN_A_TO_POSIX, oldpath, oldfullpath,
+				    PATH_MAX);
+		  cygwin_conv_path (CCP_WIN_A_TO_POSIX, newpath, newfullpath,
+				    PATH_MAX);
 		  len = strlen (oldfullpath);
 		  if (newfullpath[len] == '/'
 		      && !strncmp (oldfullpath, newfullpath, len))
Index: windows-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/windows-nat.c,v
retrieving revision 1.203
diff -u -p -r1.203 windows-nat.c
--- windows-nat.c	15 Feb 2010 17:35:49 -0000	1.203
+++ windows-nat.c	28 Feb 2010 15:07:05 -0000
@@ -71,7 +71,11 @@
 #define DebugBreakProcess		dyn_DebugBreakProcess
 #define DebugSetProcessKillOnExit	dyn_DebugSetProcessKillOnExit
 #define EnumProcessModules		dyn_EnumProcessModules
+#ifndef __CYGWIN__
 #define GetModuleFileNameExA		dyn_GetModuleFileNameExA
+#else
+#define GetModuleFileNameExW		dyn_GetModuleFileNameExW
+#endif
 #define GetModuleInformation		dyn_GetModuleInformation
 #define LookupPrivilegeValueA		dyn_LookupPrivilegeValueA
 #define OpenProcessToken		dyn_OpenProcessToken
@@ -83,8 +87,13 @@ static BOOL WINAPI (*DebugBreakProcess) 
 static BOOL WINAPI (*DebugSetProcessKillOnExit) (BOOL);
 static BOOL WINAPI (*EnumProcessModules) (HANDLE, HMODULE *, DWORD,
 					  LPDWORD);
+#ifndef __CYGWIN__
 static DWORD WINAPI (*GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
 					    DWORD);
+#else
+static DWORD WINAPI (*GetModuleFileNameExW) (HANDLE, HMODULE, LPWSTR,
+					    DWORD);
+#endif
 static BOOL WINAPI (*GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
 					    DWORD);
 static BOOL WINAPI (*LookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
@@ -483,10 +492,8 @@ get_module_name (LPVOID base_address, ch
   HMODULE *DllHandle = dh_buf;	/* Set to temporary storage for initial query */
   DWORD cbNeeded;
 #ifdef __CYGWIN__
-  char pathbuf[PATH_MAX + 1];	/* Temporary storage prior to converting to
+  wchar_t pathbuf[PATH_MAX];	/* Temporary storage prior to converting to
 				   posix form */
-#else
-  char *pathbuf = dll_name_ret;	/* Just copy directly to passed-in arg */
 #endif
 
   cbNeeded = 0;
@@ -515,13 +522,20 @@ get_module_name (LPVOID base_address, ch
       if (!base_address || mi.lpBaseOfDll == base_address)
 	{
 	  /* Try to find the name of the given module */
+#ifdef __CYGWIN__
+	  /* Cygwin prefers that the path be in /x/y/z format */
+	  len = GetModuleFileNameExW (current_process_handle,
+				      DllHandle[i], pathbuf, PATH_MAX);
+	  if (len == 0)
+	    error (_("Error getting dll name: %lu."), GetLastError ());
+	  if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, dll_name_ret,
+				PATH_MAX) < 0)
+	    error (_("Error converting dll name to POSIX: %d."), errno);
+#else
 	  len = GetModuleFileNameExA (current_process_handle,
-				      DllHandle[i], pathbuf, MAX_PATH);
+				      DllHandle[i], dll_name_ret, MAX_PATH);
 	  if (len == 0)
 	    error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
-#ifdef __CYGWIN__
-	  /* Cygwin prefers that the path be in /x/y/z format */
-	  cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
 #endif
 	  return 1;	/* success */
 	}
@@ -612,12 +626,12 @@ static struct so_list *
 windows_make_so (const char *name, LPVOID load_addr)
 {
   struct so_list *so;
+  char *p;
+#ifndef __CYGWIN__
   char buf[MAX_PATH + 1];
   char cwd[MAX_PATH + 1];
-  char *p;
   WIN32_FIND_DATA w32_fd;
   HANDLE h = FindFirstFile(name, &w32_fd);
-  MEMORY_BASIC_INFORMATION m;
 
   if (h == INVALID_HANDLE_VALUE)
     strcpy (buf, name);
@@ -635,12 +649,24 @@ windows_make_so (const char *name, LPVOI
 	  SetCurrentDirectory (cwd);
 	}
     }
-
   if (strcasecmp (buf, "ntdll.dll") == 0)
     {
       GetSystemDirectory (buf, sizeof (buf));
       strcat (buf, "\\ntdll.dll");
     }
+#else
+  wchar_t buf[PATH_MAX];
+
+  buf[0] = L'\0';
+  if (access (name, F_OK) != 0)
+    {
+      if (strcasecmp (name, "ntdll.dll") == 0)
+	{
+	  GetSystemDirectoryW (buf, sizeof (buf) / sizeof (wchar_t));
+	  wcscat (buf, L"\\ntdll.dll");
+	}
+    }
+#endif
   so = XZALLOC (struct so_list);
   so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
   so->lm_info->load_addr = load_addr;
@@ -648,7 +674,20 @@ windows_make_so (const char *name, LPVOI
 #ifndef __CYGWIN__
   strcpy (so->so_name, buf);
 #else
-  cygwin_conv_to_posix_path (buf, so->so_name);
+  if (buf[0])
+    cygwin_conv_path (CCP_WIN_W_TO_POSIX, buf, so->so_name,
+		      SO_NAME_MAX_PATH_SIZE);
+  else
+    {
+      char *rname = canonicalize_file_name (name);
+      if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
+	{
+	  strcpy (so->so_name, rname);
+	  free (rname);
+	}
+      else
+	error (_("dll path too long"));
+    }
   /* Record cygwin1.dll .text start/end.  */
   p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
   if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
@@ -687,7 +726,11 @@ windows_make_so (const char *name, LPVOI
 static char *
 get_image_name (HANDLE h, void *address, int unicode)
 {
+#ifdef __CYGWIN__
+  static char buf[PATH_MAX];
+#else
   static char buf[(2 * MAX_PATH) + 1];
+#endif
   DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
   char *address_ptr;
   int len = 0;
@@ -718,8 +761,12 @@ get_image_name (HANDLE h, void *address,
       WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
       ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
 			 &done);
-
-      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
+#ifdef __CYGWIN__
+      wcstombs (buf, unicode_address, PATH_MAX);
+#else
+      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
+			   0, 0);
+#endif
     }
 
   return buf;
@@ -731,7 +778,11 @@ static int
 handle_load_dll (void *dummy)
 {
   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
+#ifdef __CYGWIN__
+  char dll_buf[PATH_MAX];
+#else
   char dll_buf[MAX_PATH + 1];
+#endif
   char *dll_name = NULL;
 
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
@@ -1772,9 +1823,9 @@ windows_detach (struct target_ops *ops, 
 static char *
 windows_pid_to_exec_file (int pid)
 {
-  static char path[MAX_PATH + 1];
-
 #ifdef __CYGWIN__
+  static char path[PATH_MAX];
+
   /* Try to find exe name as symlink target of /proc/<pid>/exe */
   int nchars;
   char procexe[sizeof ("/proc/4294967295/exe")];
@@ -1785,6 +1836,8 @@ windows_pid_to_exec_file (int pid)
       path[nchars] = '\0';	/* Got it */
       return path;
     }
+#else
+  static char path[MAX_PATH + 1];
 #endif
 
   /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
@@ -1822,21 +1875,28 @@ static void
 windows_create_inferior (struct target_ops *ops, char *exec_file,
 		       char *allargs, char **in_env, int from_tty)
 {
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  BOOL ret;
-  DWORD flags;
-  char *args;
-  char real_path[MAXPATHLEN];
-  char *toexec;
-  char shell[MAX_PATH + 1]; /* Path to shell */
-  const char *sh;
 #ifdef __CYGWIN__
+  STARTUPINFOW si;
+  wchar_t real_path[PATH_MAX];
+  wchar_t shell[PATH_MAX]; /* Path to shell */
+  const char *sh;
+  wchar_t *toexec;
+  wchar_t *cygallargs;
+  wchar_t *args;
+  size_t len;
   int tty;
   int ostdin, ostdout, ostderr;
 #else
+  STARTUPINFOA si;
+  char real_path[PATH_MAX];
+  char shell[MAX_PATH + 1]; /* Path to shell */
+  char *toexec;
+  char *args;
   HANDLE tty;
 #endif
+  PROCESS_INFORMATION pi;
+  BOOL ret;
+  DWORD flags = 0;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
 
   if (!exec_file)
@@ -1845,44 +1905,45 @@ windows_create_inferior (struct target_o
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
+  if (new_group)
+    flags |= CREATE_NEW_PROCESS_GROUP;
+
+  if (new_console)
+    flags |= CREATE_NEW_CONSOLE;
+
 #ifdef __CYGWIN__
   if (!useshell)
     {
-      flags = DEBUG_ONLY_THIS_PROCESS;
-      cygwin_conv_to_win32_path (exec_file, real_path);
+      flags |= DEBUG_ONLY_THIS_PROCESS;
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, exec_file, real_path,
+			    PATH_MAX * sizeof (wchar_t)) < 0)
+	error (_("Error starting executable: %d"), errno);
       toexec = real_path;
+      len = mbstowcs (NULL, allargs, 0) + 1;
+      if (len == (size_t) -1)
+	error (_("Error starting executable: %d"), errno);
+      cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
+      mbstowcs (cygallargs, allargs, len);
     }
   else
     {
-      char *newallargs;
       sh = getenv ("SHELL");
       if (!sh)
 	sh = "/bin/sh";
-      cygwin_conv_to_win32_path (sh, shell);
-      newallargs = alloca (sizeof (" -c 'exec  '") + strlen (exec_file)
-			   + strlen (allargs) + 2);
-      sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
-      allargs = newallargs;
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, sh, shell, PATH_MAX) < 0)
+      	error (_("Error starting executable via shell: %d"), errno);
+      len = sizeof (L" -c 'exec  '") + mbstowcs (NULL, exec_file, 0)
+	    + mbstowcs (NULL, allargs, 0) + 2;
+      cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
+      swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
       toexec = shell;
-      flags = DEBUG_PROCESS;
+      flags |= DEBUG_PROCESS;
     }
-#else
-  toexec = exec_file;
-  flags = DEBUG_ONLY_THIS_PROCESS;
-#endif
-
-  if (new_group)
-    flags |= CREATE_NEW_PROCESS_GROUP;
-
-  if (new_console)
-    flags |= CREATE_NEW_CONSOLE;
-
-  args = alloca (strlen (toexec) + strlen (allargs) + 2);
-  strcpy (args, toexec);
-  strcat (args, " ");
-  strcat (args, allargs);
-
-#ifdef __CYGWIN__
+  args = (wchar_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
+			     * sizeof (wchar_t));
+  wcscpy (args, toexec);
+  wcscat (args, L" ");
+  wcscat (args, cygallargs);
   /* Prepare the environment vars for CreateProcess.  */
   cygwin_internal (CW_SYNC_WINENV);
 
@@ -1906,7 +1967,37 @@ windows_create_inferior (struct target_o
 	  dup2 (tty, 2);
 	}
     }
+
+  windows_init_thread_list ();
+  ret = CreateProcessW (0,
+			args,	/* command line */
+			NULL,	/* Security */
+			NULL,	/* thread */
+			TRUE,	/* inherit handles */
+			flags,	/* start flags */
+			NULL,	/* environment */
+			NULL,	/* current directory */
+			&si,
+			&pi);
+  if (tty >= 0)
+    {
+      close (tty);
+      dup2 (ostdin, 0);
+      dup2 (ostdout, 1);
+      dup2 (ostderr, 2);
+      close (ostdin);
+      close (ostdout);
+      close (ostderr);
+    }
 #else
+  args = alloca (strlen (toexec) + strlen (allargs) + 2);
+  strcpy (args, toexec);
+  strcat (args, " ");
+  strcat (args, allargs);
+
+  toexec = exec_file;
+  flags |= DEBUG_ONLY_THIS_PROCESS;
+
   if (!inferior_io_terminal)
     tty = INVALID_HANDLE_VALUE;
   else
@@ -1928,32 +2019,18 @@ windows_create_inferior (struct target_o
 	  si.dwFlags |= STARTF_USESTDHANDLES;
 	}
     }
-#endif
 
   windows_init_thread_list ();
-  ret = CreateProcess (0,
-		       args,	/* command line */
-		       NULL,	/* Security */
-		       NULL,	/* thread */
-		       TRUE,	/* inherit handles */
-		       flags,	/* start flags */
-		       NULL,	/* environment */
-		       NULL,	/* current directory */
-		       &si,
-		       &pi);
-
-#ifdef __CYGWIN__
-  if (tty >= 0)
-    {
-      close (tty);
-      dup2 (ostdin, 0);
-      dup2 (ostdout, 1);
-      dup2 (ostderr, 2);
-      close (ostdin);
-      close (ostdout);
-      close (ostderr);
-    }
-#else
+  ret = CreateProcessA (0,
+			args,	/* command line */
+			NULL,	/* Security */
+			NULL,	/* thread */
+			TRUE,	/* inherit handles */
+			flags,	/* start flags */
+			NULL,	/* environment */
+			NULL,	/* current directory */
+			&si,
+			&pi);
   if (tty != INVALID_HANDLE_VALUE)
     CloseHandle (tty);
 #endif
@@ -2220,6 +2297,10 @@ _initialize_windows_nat (void)
 
   init_windows_ops ();
 
+#ifdef __CYGWIN__
+  cygwin_internal (CW_SET_DOS_FILE_WARNING, 1);
+#endif
+
   c = add_com ("dll-symbols", class_files, dll_symbol_command,
 	       _("Load dll library symbols from FILE."));
   set_cmd_completer (c, filename_completer);
@@ -2402,11 +2483,19 @@ bad_EnumProcessModules (HANDLE w, HMODUL
 {
   return FALSE;
 }
+#ifndef __CYGWIN__
 static DWORD WINAPI
 bad_GetModuleFileNameExA (HANDLE w, HMODULE x, LPSTR y, DWORD z)
 {
   return 0;
 }
+#else
+static DWORD WINAPI
+bad_GetModuleFileNameExW (HANDLE w, HMODULE x, LPWSTR y, DWORD z)
+{
+  return 0;
+}
+#endif
 static BOOL WINAPI
 bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
 {
@@ -2456,17 +2545,32 @@ _initialize_loadable (void)
 	GetProcAddress (hm, "EnumProcessModules");
       dyn_GetModuleInformation = (void *)
 	GetProcAddress (hm, "GetModuleInformation");
+#ifndef __CYGWIN__
       dyn_GetModuleFileNameExA = (void *)
 	GetProcAddress (hm, "GetModuleFileNameExA");
+#else
+      dyn_GetModuleFileNameExW = (void *)
+	GetProcAddress (hm, "GetModuleFileNameExW");
+#endif
     }
 
-  if (!dyn_EnumProcessModules || !dyn_GetModuleInformation || !dyn_GetModuleFileNameExA)
+  if (!dyn_EnumProcessModules || !dyn_GetModuleInformation
+#ifndef __CYGWIN__
+      || !dyn_GetModuleFileNameExA
+#else
+      || !dyn_GetModuleFileNameExW
+#endif
+     )
     {
       /* Set variables to dummy versions of these processes if the function
 	 wasn't found in psapi.dll. */
       dyn_EnumProcessModules = bad_EnumProcessModules;
       dyn_GetModuleInformation = bad_GetModuleInformation;
+#ifndef __CYGWIN__
       dyn_GetModuleFileNameExA = bad_GetModuleFileNameExA;
+#else
+      dyn_GetModuleFileNameExW = bad_GetModuleFileNameExW;
+#endif
       /* 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.\nUse \"file\" or \"dll\" command to load executable/libraries directly."));


-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat



More information about the Gdb-patches mailing list