This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] windows-nat.c: Cygwin: Port to Cygwin 1.7
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Sun, 28 Feb 2010 16:08:44 +0100
- Subject: [RFA] windows-nat.c: Cygwin: Port to Cygwin 1.7
- Reply-to: gdb-patches at sourceware dot org
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 = ¤t_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