/* Target-vector operations for controlling windows child processes, for GDB.
- Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995-2019 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company.
#endif
#include <algorithm>
-#include "buildsym-legacy.h"
#include "filenames.h"
#include "symfile.h"
#include "objfiles.h"
#include "x86-nat.h"
#include "complaints.h"
#include "inf-child.h"
-#include "gdb_tilde_expand.h"
+#include "gdbsupport/gdb_tilde_expand.h"
+#include "gdbsupport/pathstuff.h"
#define AdjustTokenPrivileges dyn_AdjustTokenPrivileges
#define DebugActiveProcessStop dyn_DebugActiveProcessStop
static int have_saved_context; /* True if we've saved context from a
cygwin signal. */
#ifdef __CYGWIN__
-static CONTEXT saved_context; /* Containes the saved context from a
+static CONTEXT saved_context; /* Contains the saved context from a
cygwin signal. */
#endif
int suspended;
int reload_context;
CONTEXT context;
- STACKFRAME sf;
}
windows_thread_info;
WaitForDebugEvent */
static HANDLE current_process_handle; /* Currently executing process */
static windows_thread_info *current_thread; /* Info on currently selected thread */
-static DWORD main_thread_id; /* Thread ID of the main thread */
/* Counts of things. */
static int exception_count = 0;
static int open_process_used = 0;
/* User options. */
-static int new_console = 0;
+static bool new_console = false;
#ifdef __CYGWIN__
-static int cygwin_exceptions = 0;
+static bool cygwin_exceptions = false;
#endif
-static int new_group = 1;
-static int debug_exec = 0; /* show execution */
-static int debug_events = 0; /* show events from kernel */
-static int debug_memory = 0; /* show target memory accesses */
-static int debug_exceptions = 0; /* show target exceptions */
-static int useshell = 0; /* use shell for subprocesses */
+static bool new_group = true;
+static bool debug_exec = false; /* show execution */
+static bool debug_events = false; /* show events from kernel */
+static bool debug_memory = false; /* show target memory accesses */
+static bool debug_exceptions = false; /* show target exceptions */
+static bool useshell = false; /* use shell for subprocesses */
/* This vector maps GDB's idea of a register's number into an offset
in the windows exception context vector.
bool thread_alive (ptid_t ptid) override;
- const char *pid_to_str (ptid_t) override;
+ std::string pid_to_str (ptid_t) override;
void interrupt () override;
return NULL;
}
-/* Add a thread to the thread list. */
+/* Add a thread to the thread list.
+
+ PTID is the ptid of the thread to be added.
+ H is its Windows handle.
+ TLB is its thread local base.
+ MAIN_THREAD_P should be true if the thread to be added is
+ the main thread, false otherwise. */
+
static windows_thread_info *
-windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
+windows_add_thread (ptid_t ptid, HANDLE h, void *tlb, bool main_thread_p)
{
windows_thread_info *th;
DWORD id;
th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
th->next = thread_head.next;
thread_head.next = th;
- add_thread (ptid);
+
+ /* Add this new thread to the list of threads.
+
+ To be consistent with what's done on other platforms, we add
+ the main thread silently (in reality, this thread is really
+ more of a process to the user than a thread). */
+ if (main_thread_p)
+ add_thread_silent (ptid);
+ else
+ add_thread (ptid);
+
/* Set the debug registers for the new thread if they are used. */
if (debug_registers_used)
{
thread_head.next = NULL;
}
-/* Delete a thread from the list of threads. */
+/* Delete a thread from the list of threads.
+
+ PTID is the ptid of the thread to be deleted.
+ EXIT_CODE is the thread's exit code.
+ MAIN_THREAD_P should be true if the thread to be deleted is
+ the main thread, false otherwise. */
+
static void
-windows_delete_thread (ptid_t ptid, DWORD exit_code)
+windows_delete_thread (ptid_t ptid, DWORD exit_code, bool main_thread_p)
{
windows_thread_info *th;
DWORD id;
id = ptid.tid ();
+ /* Emit a notification about the thread being deleted.
+
+ Note that no notification was printed when the main thread
+ was created, and thus, unless in verbose mode, we should be
+ symmetrical, and avoid that notification for the main thread
+ here as well. */
+
if (info_verbose)
- printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
- else if (print_thread_events && id != main_thread_id)
+ printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid).c_str ());
+ else if (print_thread_events && !main_thread_p)
printf_unfiltered (_("[%s exited with code %u]\n"),
- target_pid_to_str (ptid), (unsigned) exit_code);
+ target_pid_to_str (ptid).c_str (),
+ (unsigned) exit_code);
+
delete_thread (find_thread_ptid (ptid));
for (th = &thread_head;
void
windows_nat_target::fetch_registers (struct regcache *regcache, int r)
{
- DWORD pid = regcache->ptid ().tid ();
- windows_thread_info *th = thread_rec (pid, TRUE);
+ DWORD tid = regcache->ptid ().tid ();
+ windows_thread_info *th = thread_rec (tid, TRUE);
/* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
void
windows_nat_target::store_registers (struct regcache *regcache, int r)
{
- DWORD pid = regcache->ptid ().tid ();
- windows_thread_info *th = thread_rec (pid, TRUE);
+ DWORD tid = regcache->ptid ().tid ();
+ windows_thread_info *th = thread_rec (tid, TRUE);
/* Check if TH exists. Windows sometimes uses a non-existent
thread id in its events. */
windows_store_one_register (regcache, th, r);
}
-/* Encapsulate the information required in a call to
- symbol_file_add_args. */
-struct safe_symbol_file_add_args
-{
- char *name;
- int from_tty;
- section_addr_info *addrs;
- int mainline;
- int flags;
- struct ui_file *err, *out;
- struct objfile *ret;
-};
-
/* Maintain a linked list of "so" information. */
struct lm_info_windows : public lm_info_base
{
if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
{
asection *text = NULL;
- CORE_ADDR text_vma;
gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
file header and the section alignment. */
cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
load_addr + 0x1000);
- cygwin_load_end = cygwin_load_start + bfd_section_size (abfd.get (),
- text);
+ cygwin_load_end = cygwin_load_start + bfd_section_size (text);
}
#endif
static void
catch_errors (void (*func) ())
{
- TRY
+ try
{
func ();
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (const gdb_exception &ex)
{
exception_print (gdb_stderr, ex);
}
- END_CATCH
}
/* Clear list of loaded DLLs. */
ourstatus->kind = TARGET_WAITKIND_STOPPED;
retval = strtoul (p, &p, 0);
if (!retval)
- retval = main_thread_id;
+ retval = current_event.dwThreadId;
else if ((x = (LPCVOID) (uintptr_t) strtoull (p, NULL, 0))
&& ReadProcessMemory (current_process_handle, x,
&saved_context,
puts_filtered ("Code (Exec/Read, Conf");
break;
default:
- printf_filtered ("Unknown type 0x%x",info.HighWord.Bits.Type);
+ printf_filtered ("Unknown type 0x%lx",
+ (unsigned long) info.HighWord.Bits.Type);
}
if ((info.HighWord.Bits.Type & 0x1) == 0)
puts_filtered(", N.Acc");
puts_filtered (")\n");
if ((info.HighWord.Bits.Type & 0x10) == 0)
puts_filtered("System selector ");
- printf_filtered ("Priviledge level = %d. ", info.HighWord.Bits.Dpl);
+ printf_filtered ("Priviledge level = %ld. ",
+ (unsigned long) info.HighWord.Bits.Dpl);
if (info.HighWord.Bits.Granularity)
puts_filtered ("Page granular.\n");
else
(unsigned) GetLastError ());
/* We can not debug anything in that case. */
}
- main_thread_id = current_event.dwThreadId;
- current_thread = windows_add_thread (
- ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
- current_event.u.CreateThread.hThread,
- current_event.u.CreateThread.lpThreadLocalBase);
- return main_thread_id;
+ current_thread
+ = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ current_event.u.CreateThread.hThread,
+ current_event.u.CreateThread.lpThreadLocalBase,
+ true /* main_thread_p */);
+ return current_event.dwThreadId;
}
void
last_sig = GDB_SIGNAL_0;
- DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
- ptid.pid (), ptid.tid (), step, sig));
+ DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=0x%x, step=%d, sig=%d);\n",
+ ptid.pid (), (unsigned) ptid.tid (), step, sig));
/* Get context for currently selected thread. */
th = thread_rec (inferior_ptid.tid (), FALSE);
}
/* Record the existence of this thread. */
thread_id = current_event.dwThreadId;
- th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
- current_event.u.CreateThread.hThread,
- current_event.u.CreateThread.lpThreadLocalBase);
+ th = windows_add_thread
+ (ptid_t (current_event.dwProcessId, 0, current_event.dwThreadId),
+ current_event.u.CreateThread.hThread,
+ current_event.u.CreateThread.lpThreadLocalBase,
+ false /* main_thread_p */);
break;
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"EXIT_THREAD_DEBUG_EVENT"));
-
- if (current_event.dwThreadId != main_thread_id)
- {
- windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
- current_event.u.ExitThread.dwExitCode);
- th = &dummy_thread_info;
- }
+ windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ current_event.u.ExitThread.dwExitCode,
+ false /* main_thread_p */);
+ th = &dummy_thread_info;
break;
case CREATE_PROCESS_DEBUG_EVENT:
break;
current_process_handle = current_event.u.CreateProcessInfo.hProcess;
- if (main_thread_id)
- windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
- main_thread_id),
- 0);
- main_thread_id = current_event.dwThreadId;
/* Add the main thread. */
- th = windows_add_thread (ptid_t (current_event.dwProcessId, 0,
- current_event.dwThreadId),
- current_event.u.CreateProcessInfo.hThread,
- current_event.u.CreateProcessInfo.lpThreadLocalBase);
+ th = windows_add_thread
+ (ptid_t (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ current_event.u.CreateProcessInfo.hThread,
+ current_event.u.CreateProcessInfo.lpThreadLocalBase,
+ true /* main_thread_p */);
thread_id = current_event.dwThreadId;
break;
}
else if (saw_create == 1)
{
+ windows_delete_thread (ptid_t (current_event.dwProcessId, 0,
+ current_event.dwThreadId),
+ 0, true /* main_thread_p */);
ourstatus->kind = TARGET_WAITKIND_EXITED;
ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
- thread_id = main_thread_id;
+ thread_id = current_event.dwThreadId;
}
break;
catch_errors (handle_load_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
- thread_id = main_thread_id;
+ thread_id = current_event.dwThreadId;
break;
case UNLOAD_DLL_DEBUG_EVENT:
catch_errors (handle_unload_dll);
ourstatus->kind = TARGET_WAITKIND_LOADED;
ourstatus->value.integer = 0;
- thread_id = main_thread_id;
+ thread_id = current_event.dwThreadId;
break;
case EXCEPTION_DEBUG_EVENT:
{
int pid = -1;
- target_terminal::ours ();
-
/* We loop when we get a non-standard exception rather than return
with a SPURIOUS because resume can try and step or modify things,
which needs a current_thread->h. But some of these exceptions mark
#endif
if (!ok)
- error (_("Can't attach to process."));
+ error (_("Can't attach to process %u (error %u)"),
+ (unsigned) pid, (unsigned) GetLastError ());
DebugSetProcessKillOnExit (FALSE);
if (exec_file)
printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
- target_pid_to_str (ptid_t (pid)));
+ target_pid_to_str (ptid_t (pid)).c_str ());
else
printf_unfiltered ("Attaching to %s\n",
- target_pid_to_str (ptid_t (pid)));
-
- gdb_flush (gdb_stdout);
+ target_pid_to_str (ptid_t (pid)).c_str ());
}
do_initial_windows_stuff (this, pid, 1);
exec_file = "";
printf_unfiltered ("Detaching from program: %s, Pid %u\n", exec_file,
(unsigned) current_event.dwProcessId);
- gdb_flush (gdb_stdout);
}
x86_cleanup_dregs ();
printf_unfiltered ("\tUsing the running image of %s %s.\n",
inf->attach_flag ? "attached" : "child",
- target_pid_to_str (inferior_ptid));
+ target_pid_to_str (inferior_ptid).c_str ());
}
/* Modify CreateProcess parameters for use of a new separate console.
}
else
{
- sh = getenv ("SHELL");
- if (!sh)
- sh = "/bin/sh";
+ sh = get_shell ();
if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, sh, shell, __PMAX) < 0)
error (_("Error starting executable via shell: %d"), errno);
#ifdef __USEWIDE
redirect_inferior_handles (allargs, allargs_copy,
&fd_inp, &fd_out, &fd_err);
if (errno)
- warning (_("Error in redirection: %s."), strerror (errno));
+ warning (_("Error in redirection: %s."), safe_strerror (errno));
else
errno = e;
allargs_len = strlen (allargs_copy);
}
/* Convert pid to printable format. */
-const char *
+std::string
windows_nat_target::pid_to_str (ptid_t ptid)
{
- static char buf[80];
-
if (ptid.tid () != 0)
- {
- snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
- ptid.pid (), ptid.tid ());
- return buf;
- }
+ return string_printf ("Thread %d.0x%lx", ptid.pid (), ptid.tid ());
return normal_pid_to_str (ptid);
}