| Index: gdb/windows-nat.c
|
| diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
|
| index f16588adfdac6e335d48895c8dc3d7935b5b51f2..f0545fcc967f94a1ddf90917a82bf842a836b3c1 100644
|
| --- a/gdb/windows-nat.c
|
| +++ b/gdb/windows-nat.c
|
| @@ -1,6 +1,6 @@
|
| /* Target-vector operations for controlling windows child processes, for GDB.
|
|
|
| - Copyright (C) 1995-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1995-2013 Free Software Foundation, Inc.
|
|
|
| Contributed by Cygnus Solutions, A Red Hat Company.
|
|
|
| @@ -49,11 +49,11 @@
|
| #include "filenames.h"
|
| #include "symfile.h"
|
| #include "objfiles.h"
|
| +#include "gdb_bfd.h"
|
| #include "gdb_obstack.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "gdbthread.h"
|
| #include "gdbcmd.h"
|
| -#include <sys/param.h>
|
| #include <unistd.h>
|
| #include "exec.h"
|
| #include "solist.h"
|
| @@ -288,8 +288,8 @@ static void
|
| check (BOOL ok, const char *file, int line)
|
| {
|
| if (!ok)
|
| - printf_filtered ("error return %s:%d was %lu\n", file, line,
|
| - GetLastError ());
|
| + printf_filtered ("error return %s:%d was %u\n", file, line,
|
| + (unsigned) GetLastError ());
|
| }
|
|
|
| /* Find a thread record given a thread id. If GET_CONTEXT is not 0,
|
| @@ -310,8 +310,10 @@ thread_rec (DWORD id, int get_context)
|
| if (SuspendThread (th->h) == (DWORD) -1)
|
| {
|
| DWORD err = GetLastError ();
|
| - warning (_("SuspendThread failed. (winerr %d)"),
|
| - (int) err);
|
| +
|
| + warning (_("SuspendThread (tid=0x%x) failed."
|
| + " (winerr %u)"),
|
| + (unsigned) id, (unsigned) err);
|
| return NULL;
|
| }
|
| th->suspended = 1;
|
| @@ -385,7 +387,7 @@ windows_init_thread_list (void)
|
|
|
| /* Delete a thread from the list of threads. */
|
| static void
|
| -windows_delete_thread (ptid_t ptid)
|
| +windows_delete_thread (ptid_t ptid, DWORD exit_code)
|
| {
|
| thread_info *th;
|
| DWORD id;
|
| @@ -396,6 +398,9 @@ windows_delete_thread (ptid_t ptid)
|
|
|
| if (info_verbose)
|
| printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
|
| + else if (print_thread_events && id != main_thread_id)
|
| + printf_unfiltered (_("[%s exited with code %u]\n"),
|
| + target_pid_to_str (ptid), (unsigned) exit_code);
|
| delete_thread (ptid);
|
|
|
| for (th = &thread_head;
|
| @@ -575,7 +580,8 @@ get_module_name (LPVOID base_address, char *dll_name_ret)
|
| len = GetModuleFileNameEx (current_process_handle,
|
| DllHandle[i], pathbuf, __PMAX);
|
| if (len == 0)
|
| - error (_("Error getting dll name: %lu."), GetLastError ());
|
| + error (_("Error getting dll name: %u."),
|
| + (unsigned) GetLastError ());
|
| if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, dll_name_ret,
|
| __PMAX) < 0)
|
| error (_("Error converting dll name to POSIX: %d."), errno);
|
| @@ -752,7 +758,7 @@ windows_make_so (const char *name, LPVOID load_addr)
|
| asection *text = NULL;
|
| CORE_ADDR text_vma;
|
|
|
| - abfd = bfd_openr (so->so_name, "pei-i386");
|
| + abfd = gdb_bfd_open (so->so_name, "pei-i386", -1);
|
|
|
| if (!abfd)
|
| return so;
|
| @@ -762,7 +768,7 @@ windows_make_so (const char *name, LPVOID load_addr)
|
|
|
| if (!text)
|
| {
|
| - bfd_close (abfd);
|
| + gdb_bfd_unref (abfd);
|
| return so;
|
| }
|
|
|
| @@ -773,7 +779,7 @@ windows_make_so (const char *name, LPVOID load_addr)
|
| load_addr + 0x1000);
|
| cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
|
|
|
| - bfd_close (abfd);
|
| + gdb_bfd_unref (abfd);
|
| }
|
| #endif
|
|
|
| @@ -841,11 +847,31 @@ handle_load_dll (void *dummy)
|
|
|
| dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
|
|
|
| + /* Try getting the DLL name by searching the list of known modules
|
| + and matching their base address against this new DLL's base address.
|
| +
|
| + FIXME: brobecker/2013-12-10:
|
| + It seems odd to be going through this search if the DLL name could
|
| + simply be extracted via "event->lpImageName". Moreover, some
|
| + experimentation with various versions of Windows seem to indicate
|
| + that it might still be too early for this DLL to be listed when
|
| + querying the system about the current list of modules, thus making
|
| + this attempt pointless.
|
| +
|
| + This code can therefore probably be removed. But at the time of
|
| + this writing, we are too close to creating the GDB 7.7 branch
|
| + for us to make such a change. We are therefore defering it. */
|
| +
|
| if (!get_module_name (event->lpBaseOfDll, dll_buf))
|
| dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
|
|
|
| dll_name = dll_buf;
|
|
|
| + /* Try getting the DLL name via the lpImageName field of the event.
|
| + Note that Microsoft documents this fields as strictly optional,
|
| + in the sense that it might be NULL. And the first DLL event in
|
| + particular is explicitly documented as "likely not pass[ed]"
|
| + (source: MSDN LOAD_DLL_DEBUG_INFO structure). */
|
| if (*dll_name == '\0')
|
| dll_name = get_image_name (current_process_handle,
|
| event->lpImageName, event->fUnicode);
|
| @@ -879,13 +905,13 @@ handle_unload_dll (void *dummy)
|
| if (so->next->lm_info->load_addr == lpBaseOfDll)
|
| {
|
| struct so_list *sodel = so->next;
|
| +
|
| so->next = sodel->next;
|
| if (!so->next)
|
| solib_end = so;
|
| DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
|
|
|
| windows_free_so (sodel);
|
| - solib_add (NULL, 0, NULL, auto_solib_add);
|
| return 1;
|
| }
|
|
|
| @@ -967,16 +993,18 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
|
| char *p;
|
| int sig = strtol (s + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
|
| int gotasig = gdb_signal_from_host (sig);
|
| +
|
| ourstatus->value.sig = gotasig;
|
| if (gotasig)
|
| {
|
| LPCVOID x;
|
| - DWORD n;
|
| + SIZE_T n;
|
| +
|
| ourstatus->kind = TARGET_WAITKIND_STOPPED;
|
| retval = strtoul (p, &p, 0);
|
| if (!retval)
|
| retval = main_thread_id;
|
| - else if ((x = (LPCVOID) strtoul (p, &p, 0))
|
| + else if ((x = (LPCVOID) (uintptr_t) strtoull (p, NULL, 0))
|
| && ReadProcessMemory (current_process_handle, x,
|
| &saved_context,
|
| __COPY_CONTEXT_SIZE, &n)
|
| @@ -999,7 +1027,7 @@ display_selector (HANDLE thread, DWORD sel)
|
| if (GetThreadSelectorEntry (thread, sel, &info))
|
| {
|
| int base, limit;
|
| - printf_filtered ("0x%03lx: ", sel);
|
| + printf_filtered ("0x%03x: ", (unsigned) sel);
|
| if (!info.HighWord.Bits.Pres)
|
| {
|
| puts_filtered ("Segment not present\n");
|
| @@ -1063,7 +1091,7 @@ display_selector (HANDLE thread, DWORD sel)
|
| if (err == ERROR_NOT_SUPPORTED)
|
| printf_filtered ("Function not supported\n");
|
| else
|
| - printf_filtered ("Invalid selector 0x%lx.\n",sel);
|
| + printf_filtered ("Invalid selector 0x%x.\n", (unsigned) sel);
|
| return 0;
|
| }
|
| }
|
| @@ -1227,8 +1255,8 @@ handle_exception (struct target_waitstatus *ourstatus)
|
| /* Treat unhandled first chance exceptions specially. */
|
| if (current_event.u.Exception.dwFirstChance)
|
| return -1;
|
| - printf_unfiltered ("gdb: unknown target exception 0x%08lx at %s\n",
|
| - current_event.u.Exception.ExceptionRecord.ExceptionCode,
|
| + printf_unfiltered ("gdb: unknown target exception 0x%08x at %s\n",
|
| + (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
|
| host_address_to_string (
|
| current_event.u.Exception.ExceptionRecord.ExceptionAddress));
|
| ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
|
| @@ -1248,8 +1276,9 @@ windows_continue (DWORD continue_status, int id)
|
| thread_info *th;
|
| BOOL res;
|
|
|
| - DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%lx, %s);\n",
|
| - current_event.dwProcessId, current_event.dwThreadId,
|
| + DEBUG_EVENTS (("ContinueDebugEvent (cpid=%d, ctid=0x%x, %s);\n",
|
| + (unsigned) current_event.dwProcessId,
|
| + (unsigned) current_event.dwThreadId,
|
| continue_status == DBG_CONTINUE ?
|
| "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
|
|
|
| @@ -1296,8 +1325,8 @@ fake_create_process (void)
|
| open_process_used = 1;
|
| else
|
| {
|
| - error (_("OpenProcess call failed, GetLastError = %lud"),
|
| - GetLastError ());
|
| + error (_("OpenProcess call failed, GetLastError = %u"),
|
| + (unsigned) GetLastError ());
|
| /* We can not debug anything in that case. */
|
| }
|
| main_thread_id = current_event.dwThreadId;
|
| @@ -1456,7 +1485,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| switch (event_code)
|
| {
|
| case CREATE_THREAD_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "CREATE_THREAD_DEBUG_EVENT"));
|
| @@ -1485,7 +1514,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case EXIT_THREAD_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "EXIT_THREAD_DEBUG_EVENT"));
|
| @@ -1493,13 +1522,14 @@ get_windows_debug_event (struct target_ops *ops,
|
| if (current_event.dwThreadId != main_thread_id)
|
| {
|
| windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
|
| - current_event.dwThreadId));
|
| + current_event.dwThreadId),
|
| + current_event.u.ExitThread.dwExitCode);
|
| th = &dummy_thread_info;
|
| }
|
| break;
|
|
|
| case CREATE_PROCESS_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "CREATE_PROCESS_DEBUG_EVENT"));
|
| @@ -1510,7 +1540,8 @@ get_windows_debug_event (struct target_ops *ops,
|
| current_process_handle = current_event.u.CreateProcessInfo.hProcess;
|
| if (main_thread_id)
|
| windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
|
| - main_thread_id));
|
| + main_thread_id),
|
| + 0);
|
| main_thread_id = current_event.dwThreadId;
|
| /* Add the main thread. */
|
| th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
|
| @@ -1521,7 +1552,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case EXIT_PROCESS_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "EXIT_PROCESS_DEBUG_EVENT"));
|
| @@ -1541,7 +1572,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case LOAD_DLL_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "LOAD_DLL_DEBUG_EVENT"));
|
| @@ -1555,7 +1586,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case UNLOAD_DLL_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "UNLOAD_DLL_DEBUG_EVENT"));
|
| @@ -1568,7 +1599,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case EXCEPTION_DEBUG_EVENT:
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "EXCEPTION_DEBUG_EVENT"));
|
| @@ -1590,7 +1621,7 @@ get_windows_debug_event (struct target_ops *ops,
|
| break;
|
|
|
| case OUTPUT_DEBUG_STRING_EVENT: /* Message from the kernel. */
|
| - DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
|
| + DEBUG_EVENTS (("gdb: kernel event for pid=%u tid=0x%x code=%s)\n",
|
| (unsigned) current_event.dwProcessId,
|
| (unsigned) current_event.dwThreadId,
|
| "OUTPUT_DEBUG_STRING_EVENT"));
|
| @@ -1602,11 +1633,11 @@ get_windows_debug_event (struct target_ops *ops,
|
| default:
|
| if (saw_create != 1)
|
| break;
|
| - printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
|
| - (DWORD) current_event.dwProcessId,
|
| - (DWORD) current_event.dwThreadId);
|
| - printf_unfiltered (" unknown event code %ld\n",
|
| - current_event.dwDebugEventCode);
|
| + printf_unfiltered ("gdb: kernel event for pid=%u tid=0x%x\n",
|
| + (unsigned) current_event.dwProcessId,
|
| + (unsigned) current_event.dwThreadId);
|
| + printf_unfiltered (" unknown event code %u\n",
|
| + (unsigned) current_event.dwDebugEventCode);
|
| break;
|
| }
|
|
|
| @@ -1692,6 +1723,64 @@ windows_wait (struct target_ops *ops,
|
| }
|
| }
|
|
|
| +/* On certain versions of Windows, the information about ntdll.dll
|
| + is not available yet at the time we get the LOAD_DLL_DEBUG_EVENT,
|
| + thus preventing us from reporting this DLL as an SO. This has been
|
| + witnessed on Windows 8.1, for instance. A possible explanation
|
| + is that ntdll.dll might be mapped before the SO info gets created
|
| + by the Windows system -- ntdll.dll is the first DLL to be reported
|
| + via LOAD_DLL_DEBUG_EVENT and other DLLs do not seem to suffer from
|
| + that problem.
|
| +
|
| + If we indeed are missing ntdll.dll, this function tries to recover
|
| + from this issue, after the fact. Do nothing if we encounter any
|
| + issue trying to locate that DLL. */
|
| +
|
| +static void
|
| +windows_ensure_ntdll_loaded (void)
|
| +{
|
| + struct so_list *so;
|
| + HMODULE dummy_hmodule;
|
| + DWORD cb_needed;
|
| + HMODULE *hmodules;
|
| + int i;
|
| +
|
| + for (so = solib_start.next; so != NULL; so = so->next)
|
| + if (FILENAME_CMP (lbasename (so->so_name), "ntdll.dll") == 0)
|
| + return; /* ntdll.dll already loaded, nothing to do. */
|
| +
|
| + if (EnumProcessModules (current_process_handle, &dummy_hmodule,
|
| + sizeof (HMODULE), &cb_needed) == 0)
|
| + return;
|
| +
|
| + if (cb_needed < 1)
|
| + return;
|
| +
|
| + hmodules = (HMODULE *) alloca (cb_needed);
|
| + if (EnumProcessModules (current_process_handle, hmodules,
|
| + cb_needed, &cb_needed) == 0)
|
| + return;
|
| +
|
| + for (i = 0; i < (int) (cb_needed / sizeof (HMODULE)); i++)
|
| + {
|
| + MODULEINFO mi;
|
| + char dll_name[__PMAX];
|
| +
|
| + if (GetModuleInformation (current_process_handle, hmodules[i],
|
| + &mi, sizeof (mi)) == 0)
|
| + continue;
|
| + if (GetModuleFileNameEx (current_process_handle, hmodules[i],
|
| + dll_name, sizeof (dll_name)) == 0)
|
| + continue;
|
| + if (FILENAME_CMP (lbasename (dll_name), "ntdll.dll") == 0)
|
| + {
|
| + solib_end->next = windows_make_so (dll_name, mi.lpBaseOfDll);
|
| + solib_end = solib_end->next;
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| static void
|
| do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
|
| {
|
| @@ -1745,6 +1834,14 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
|
| break;
|
| }
|
|
|
| + /* FIXME: brobecker/2013-12-10: We should try another approach where
|
| + we first ignore all DLL load/unload events up until this point,
|
| + and then iterate over all modules to create the associated shared
|
| + objects. This is a fairly significant change, however, and we are
|
| + close to creating a release branch, so we are delaying it a bit,
|
| + after the branch is created. */
|
| + windows_ensure_ntdll_loaded ();
|
| +
|
| windows_initialization_done = 1;
|
| inf->control.stop_soon = NO_STOP_QUIETLY;
|
| stop_after_trap = 0;
|
| @@ -1855,7 +1952,7 @@ windows_attach (struct target_ops *ops, char *args, int from_tty)
|
| }
|
|
|
| static void
|
| -windows_detach (struct target_ops *ops, char *args, int from_tty)
|
| +windows_detach (struct target_ops *ops, const char *args, int from_tty)
|
| {
|
| int detached = 1;
|
|
|
| @@ -1864,8 +1961,8 @@ windows_detach (struct target_ops *ops, char *args, int from_tty)
|
|
|
| if (!DebugActiveProcessStop (current_event.dwProcessId))
|
| {
|
| - error (_("Can't detach process %lu (error %lu)"),
|
| - current_event.dwProcessId, GetLastError ());
|
| + error (_("Can't detach process %u (error %u)"),
|
| + (unsigned) current_event.dwProcessId, (unsigned) GetLastError ());
|
| detached = 0;
|
| }
|
| DebugSetProcessKillOnExit (FALSE);
|
| @@ -1875,11 +1972,12 @@ windows_detach (struct target_ops *ops, char *args, int from_tty)
|
| char *exec_file = get_exec_file (0);
|
| if (exec_file == 0)
|
| exec_file = "";
|
| - printf_unfiltered ("Detaching from program: %s, Pid %lu\n", exec_file,
|
| - current_event.dwProcessId);
|
| + printf_unfiltered ("Detaching from program: %s, Pid %u\n", exec_file,
|
| + (unsigned) current_event.dwProcessId);
|
| gdb_flush (gdb_stdout);
|
| }
|
|
|
| + i386_cleanup_dregs ();
|
| inferior_ptid = null_ptid;
|
| detach_inferior (current_event.dwProcessId);
|
|
|
| @@ -1894,7 +1992,8 @@ windows_pid_to_exec_file (int pid)
|
| /* Try to find exe name as symlink target of /proc/<pid>/exe. */
|
| int nchars;
|
| char procexe[sizeof ("/proc/4294967295/exe")];
|
| - sprintf (procexe, "/proc/%u/exe", pid);
|
| +
|
| + xsnprintf (procexe, sizeof (procexe), "/proc/%u/exe", pid);
|
| nchars = readlink (procexe, path, sizeof(path));
|
| if (nchars > 0 && nchars < sizeof (path))
|
| {
|
| @@ -2035,6 +2134,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
|
| char shell[__PMAX]; /* Path to shell */
|
| char *toexec;
|
| char *args;
|
| + size_t args_len;
|
| HANDLE tty;
|
| char *w32env;
|
| char *temp;
|
| @@ -2091,10 +2191,10 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
|
| cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
|
| swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
|
| #else
|
| - cygallargs = (char *)
|
| - alloca (sizeof (" -c 'exec '") + strlen (exec_file)
|
| - + strlen (allargs) + 2);
|
| - sprintf (cygallargs, " -c 'exec %s %s'", exec_file, allargs);
|
| + len = (sizeof (" -c 'exec '") + strlen (exec_file)
|
| + + strlen (allargs) + 2);
|
| + cygallargs = (char *) alloca (len);
|
| + xsnprintf (cygallargs, len, " -c 'exec %s %s'", exec_file, allargs);
|
| #endif
|
| toexec = shell;
|
| flags |= DEBUG_PROCESS;
|
| @@ -2187,10 +2287,13 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
|
| }
|
| #else
|
| toexec = exec_file;
|
| - args = alloca (strlen (toexec) + strlen (allargs) + 2);
|
| - strcpy (args, toexec);
|
| - strcat (args, " ");
|
| - strcat (args, allargs);
|
| + /* Build the command line, a space-separated list of tokens where
|
| + the first token is the name of the module to be executed.
|
| + To avoid ambiguities introduced by spaces in the module name,
|
| + we quote it. */
|
| + args_len = strlen (toexec) + 2 /* quotes */ + strlen (allargs) + 2;
|
| + args = alloca (args_len);
|
| + xsnprintf (args, args_len, "\"%s\" %s", toexec, allargs);
|
|
|
| flags |= DEBUG_ONLY_THIS_PROCESS;
|
|
|
| @@ -2257,7 +2360,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
|
| #endif
|
|
|
| if (!ret)
|
| - error (_("Error creating process %s, (error %d)."),
|
| + error (_("Error creating process %s, (error %u)."),
|
| exec_file, (unsigned) GetLastError ());
|
|
|
| CloseHandle (pi.hThread);
|
| @@ -2298,33 +2401,43 @@ windows_stop (ptid_t ptid)
|
| registers_changed (); /* refresh register state */
|
| }
|
|
|
| -static int
|
| -windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
|
| - int write, struct mem_attrib *mem,
|
| - struct target_ops *target)
|
| +/* Helper for windows_xfer_partial that handles memory transfers.
|
| + Arguments are like target_xfer_partial. */
|
| +
|
| +static LONGEST
|
| +windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
|
| + ULONGEST memaddr, LONGEST len)
|
| {
|
| SIZE_T done = 0;
|
| - if (write)
|
| + BOOL success;
|
| + DWORD lasterror = 0;
|
| +
|
| + if (writebuf != NULL)
|
| {
|
| - DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
|
| - len, (DWORD) (uintptr_t) memaddr));
|
| - if (!WriteProcessMemory (current_process_handle,
|
| - (LPVOID) (uintptr_t) memaddr, our,
|
| - len, &done))
|
| - done = 0;
|
| + DEBUG_MEM (("gdb: write target memory, %s bytes at %s\n",
|
| + plongest (len), core_addr_to_string (memaddr)));
|
| + success = WriteProcessMemory (current_process_handle,
|
| + (LPVOID) (uintptr_t) memaddr, writebuf,
|
| + len, &done);
|
| + if (!success)
|
| + lasterror = GetLastError ();
|
| FlushInstructionCache (current_process_handle,
|
| (LPCVOID) (uintptr_t) memaddr, len);
|
| }
|
| else
|
| {
|
| - DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
|
| - len, (DWORD) (uintptr_t) memaddr));
|
| - if (!ReadProcessMemory (current_process_handle,
|
| - (LPCVOID) (uintptr_t) memaddr, our,
|
| - len, &done))
|
| - done = 0;
|
| + DEBUG_MEM (("gdb: read target memory, %s bytes at %s\n",
|
| + plongest (len), core_addr_to_string (memaddr)));
|
| + success = ReadProcessMemory (current_process_handle,
|
| + (LPCVOID) (uintptr_t) memaddr, readbuf,
|
| + len, &done);
|
| + if (!success)
|
| + lasterror = GetLastError ();
|
| }
|
| - return done;
|
| + if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
|
| + return done;
|
| + else
|
| + return success ? done : TARGET_XFER_E_IO;
|
| }
|
|
|
| static void
|
| @@ -2358,10 +2471,10 @@ windows_can_run (void)
|
| }
|
|
|
| static void
|
| -windows_close (int x)
|
| +windows_close (void)
|
| {
|
| DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
|
| - PIDGET (inferior_ptid)));
|
| + ptid_get_pid (inferior_ptid)));
|
| }
|
|
|
| /* Convert pid to printable format. */
|
| @@ -2399,17 +2512,19 @@ windows_xfer_shared_libraries (struct target_ops *ops,
|
| for (so = solib_start.next; so; so = so->next)
|
| windows_xfer_shared_library (so->so_name, (CORE_ADDR)
|
| (uintptr_t) so->lm_info->load_addr,
|
| - target_gdbarch, &obstack);
|
| + target_gdbarch (), &obstack);
|
| obstack_grow_str0 (&obstack, "</library-list>\n");
|
|
|
| buf = obstack_finish (&obstack);
|
| len_avail = strlen (buf);
|
| if (offset >= len_avail)
|
| - return 0;
|
| -
|
| - if (len > len_avail - offset)
|
| - len = len_avail - offset;
|
| - memcpy (readbuf, buf + offset, len);
|
| + len= 0;
|
| + else
|
| + {
|
| + if (len > len_avail - offset)
|
| + len = len_avail - offset;
|
| + memcpy (readbuf, buf + offset, len);
|
| + }
|
|
|
| obstack_free (&obstack, NULL);
|
| return len;
|
| @@ -2423,13 +2538,7 @@ windows_xfer_partial (struct target_ops *ops, enum target_object object,
|
| switch (object)
|
| {
|
| case TARGET_OBJECT_MEMORY:
|
| - if (readbuf)
|
| - return (*ops->deprecated_xfer_memory) (offset, readbuf,
|
| - len, 0/*read*/, NULL, ops);
|
| - if (writebuf)
|
| - return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
|
| - len, 1/*write*/, NULL, ops);
|
| - return -1;
|
| + return windows_xfer_memory (readbuf, writebuf, offset, len);
|
|
|
| case TARGET_OBJECT_LIBRARIES:
|
| return windows_xfer_shared_libraries (ops, object, annex, readbuf,
|
| @@ -2483,7 +2592,6 @@ init_windows_ops (void)
|
| windows_ops.to_fetch_registers = windows_fetch_inferior_registers;
|
| windows_ops.to_store_registers = windows_store_inferior_registers;
|
| windows_ops.to_prepare_to_store = windows_prepare_to_store;
|
| - windows_ops.deprecated_xfer_memory = windows_xfer_memory;
|
| windows_ops.to_xfer_partial = windows_xfer_partial;
|
| windows_ops.to_files_info = windows_files_info;
|
| windows_ops.to_insert_breakpoint = memory_insert_breakpoint;
|
| @@ -2719,8 +2827,9 @@ _initialize_check_for_gdb_ini (void)
|
| {
|
| int len = strlen (oldini);
|
| char *newini = alloca (len + 1);
|
| - sprintf (newini, "%.*s.gdbinit",
|
| - (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
|
| +
|
| + xsnprintf (newini, len + 1, "%.*s.gdbinit",
|
| + (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
|
| warning (_("obsolete '%s' found. Rename to '%s'."), oldini, newini);
|
| }
|
| }
|
|
|