From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22714 invoked by alias); 13 Oct 2007 02:41:29 -0000 Received: (qmail 22638 invoked by uid 22791); 13 Oct 2007 02:41:26 -0000 X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 13 Oct 2007 02:41:21 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 168B01E6912; Fri, 12 Oct 2007 22:41:19 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id we47excfIEQD; Fri, 12 Oct 2007 22:41:18 -0400 (EDT) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id 628CC1E68FE; Fri, 12 Oct 2007 22:41:18 -0400 (EDT) Received: by joel.gnat.com (Postfix, from userid 1000) id 081CEE7B58; Fri, 12 Oct 2007 19:41:16 -0700 (PDT) Date: Sat, 13 Oct 2007 02:41:00 -0000 From: Joel Brobecker To: Eli Zaretskii Cc: Kai.Tietz@onevision.com, gdb@sourceware.org Subject: Re: Support of gdb for Windows 64 native systems Message-ID: <20071013024116.GB29152@adacore.com> References: <20071011142348.GA18239@caradoc.them.org> <20071011145549.GA19918@caradoc.them.org> <20071012161132.GE4044@adacore.com> <20071012174218.GH4044@adacore.com> <20071012222842.GD21800@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="HlL+5n6rz5pIUxbD" Content-Disposition: inline In-Reply-To: <20071012222842.GD21800@adacore.com> User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2007-10/txt/msg00091.txt.bz2 --HlL+5n6rz5pIUxbD Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 2592 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 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 --HlL+5n6rz5pIUxbD Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mingw.diff" Content-length: 15359 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 #include #include +#ifdef HAVE_SYS_CYGWIN_H #include +#endif #include #include "buildsym.h" @@ -51,6 +51,9 @@ #include "gdbthread.h" #include "gdbcmd.h" #include +#ifdef __MINGW32__ + #define MAXPATHLEN PATH_MAX +#endif #include #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 +#endif #include #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)) { --HlL+5n6rz5pIUxbD--