From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31711 invoked by alias); 28 Feb 2010 15:09:00 -0000 Received: (qmail 31665 invoked by uid 22791); 28 Feb 2010 15:08:52 -0000 X-Spam-Check-By: sourceware.org Received: from aquarius.hirmke.de (HELO calimero.vinschen.de) (217.91.18.234) by sourceware.org (qpsmtpd/0.83/v0.83-20-g38e4449) with ESMTP; Sun, 28 Feb 2010 15:08:47 +0000 Received: by calimero.vinschen.de (Postfix, from userid 500) id 341216D42F5; Sun, 28 Feb 2010 16:08:44 +0100 (CET) Date: Sun, 28 Feb 2010 15:09:00 -0000 From: Corinna Vinschen To: gdb-patches@sourceware.org Subject: [RFA] windows-nat.c: Cygwin: Port to Cygwin 1.7 Message-ID: <20100228150844.GH5683@calimero.vinschen.de> Reply-To: gdb-patches@sourceware.org Mail-Followup-To: gdb-patches@sourceware.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-02/txt/msg00677.txt.bz2 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//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