aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me+cygwin@cgf.cx>2003-12-26 04:29:22 +0000
committerChristopher Faylor <me+cygwin@cgf.cx>2003-12-26 04:29:22 +0000
commit3ade53336e08ff84a0b150acaafd41983c870472 (patch)
tree88cd2db621f1d4af1352f210313b9af26db0eddd
parent87a45c96062d658ca83b50aa060a648bf5f5f1ff (diff)
downloadgdb-3ade53336e08ff84a0b150acaafd41983c870472.zip
gdb-3ade53336e08ff84a0b150acaafd41983c870472.tar.gz
gdb-3ade53336e08ff84a0b150acaafd41983c870472.tar.bz2
Fix for PR threads/1048
* win32-nat.c (thread_info_struct): Add reload_context flag. (thread_rec): Don't reload thread context here. Just set a flag. (do_child_fetch_inferior_registers): Reload thread context here if appropriate. Avoid doing anything if current_thread is NULL thanks to strange Windows behavior. (child_fetch_inferior_registers): Avoid doing anything if current_thread is NULL. (do_child_store_inferior_registers): Ditto. (child_store_inferior_registers): Ditto. (child_kill_inferior): Ditto. (fake_create_process): Pretend to create a process for pathological windows attach situation. (get_child_debug_event): Call fake_create_process when the first event noticed is thread creation rather than process creation. (child_attach): Always set attach_flag when attaching. (child_create_inferior): Set attach_flag to zero since we're not attaching.
-rw-r--r--gdb/ChangeLog21
-rw-r--r--gdb/win32-nat.c83
-rw-r--r--gdb/windows-nat.c83
3 files changed, 131 insertions, 56 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e0f06d9..fc83580 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,26 @@
2003-12-25 Christopher Faylor <cgf@redhat.com>
+ Fix for PR threads/1048
+ * win32-nat.c (thread_info_struct): Add reload_context flag.
+ (thread_rec): Don't reload thread context here. Just set a flag.
+ (do_child_fetch_inferior_registers): Reload thread context here if
+ appropriate. Avoid doing anything if current_thread is NULL thanks to
+ strange Windows behavior.
+ (child_fetch_inferior_registers): Avoid doing anything if
+ current_thread is NULL.
+ (do_child_store_inferior_registers): Ditto.
+ (child_store_inferior_registers): Ditto.
+ (child_kill_inferior): Ditto.
+ (fake_create_process): Pretend to create a process for pathological
+ windows attach situation.
+ (get_child_debug_event): Call fake_create_process when the first event
+ noticed is thread creation rather than process creation.
+ (child_attach): Always set attach_flag when attaching.
+ (child_create_inferior): Set attach_flag to zero since we're not
+ attaching.
+
+2003-12-25 Christopher Faylor <cgf@redhat.com>
+
* win32-nat.c (get_child_debug_event): Keep main thread id around even
after thread exits since Windows insists on continuing to report events
against it.
diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c
index c29bcc0..c28e26a 100644
--- a/gdb/win32-nat.c
+++ b/gdb/win32-nat.c
@@ -108,6 +108,7 @@ typedef struct thread_info_struct
HANDLE h;
char *name;
int suspend_count;
+ int reload_context;
CONTEXT context;
STACKFRAME sf;
}
@@ -228,7 +229,6 @@ check (BOOL ok, const char *file, int line)
GetLastError ());
}
-
/* Find a thread record given a thread id.
If get_context then also retrieve the context for this
thread. */
@@ -246,19 +246,7 @@ thread_rec (DWORD id, int get_context)
th->suspend_count = SuspendThread (th->h) + 1;
else if (get_context < 0)
th->suspend_count = -1;
-
- th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
- GetThreadContext (th->h, &th->context);
- if (id == current_event.dwThreadId)
- {
- /* Copy dr values from that thread. */
- dr[0] = th->context.Dr0;
- dr[1] = th->context.Dr1;
- dr[2] = th->context.Dr2;
- dr[3] = th->context.Dr3;
- dr[6] = th->context.Dr6;
- dr[7] = th->context.Dr7;
- }
+ th->reload_context = 1;
}
return th;
}
@@ -349,6 +337,24 @@ do_child_fetch_inferior_registers (int r)
char *context_offset = ((char *) &current_thread->context) + mappings[r];
long l;
+ if (!current_thread)
+ return;
+
+ if (current_thread->reload_context)
+ {
+ thread_info *th = current_thread;
+ th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+ GetThreadContext (th->h, &th->context);
+ /* Copy dr values from that thread. */
+ dr[0] = th->context.Dr0;
+ dr[1] = th->context.Dr1;
+ dr[2] = th->context.Dr2;
+ dr[3] = th->context.Dr3;
+ dr[6] = th->context.Dr6;
+ dr[7] = th->context.Dr7;
+ current_thread->reload_context = 0;
+ }
+
#define I387_ST0_REGNUM I386_ST0_REGNUM
if (r == I387_FISEG_REGNUM)
@@ -376,13 +382,16 @@ static void
child_fetch_inferior_registers (int r)
{
current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
- do_child_fetch_inferior_registers (r);
+ if (current_thread)
+ do_child_fetch_inferior_registers (r);
}
static void
do_child_store_inferior_registers (int r)
{
- if (r >= 0)
+ if (!current_thread)
+ /* nothing to do */;
+ else if (r >= 0)
regcache_collect (r, ((char *) &current_thread->context) + mappings[r]);
else
{
@@ -396,7 +405,8 @@ static void
child_store_inferior_registers (int r)
{
current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
- do_child_store_inferior_registers (r);
+ if (current_thread)
+ do_child_store_inferior_registers (r);
}
static int psapi_loaded = 0;
@@ -1179,7 +1189,7 @@ child_continue (DWORD continue_status, int id)
th->suspend_count = 0;
if (debug_registers_changed)
{
- /* Only change the value of the debug reisters */
+ /* Only change the value of the debug registers */
th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
th->context.Dr0 = dr[0];
th->context.Dr1 = dr[1];
@@ -1197,6 +1207,17 @@ child_continue (DWORD continue_status, int id)
return res;
}
+DWORD
+fake_create_process ()
+{
+ current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
+ current_event.dwProcessId);
+ main_thread_id = current_event.dwThreadId;
+ current_thread = child_add_thread (main_thread_id,
+ current_event.u.CreateThread.hThread);
+ return main_thread_id;
+}
+
/* Get the next event from the child. Return 1 if the event requires
handling by WFI (or whatever).
*/
@@ -1229,7 +1250,14 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
(unsigned) current_event.dwThreadId,
"CREATE_THREAD_DEBUG_EVENT"));
if (saw_create != 1)
- break;
+ {
+ if (!saw_create && attach_flag)
+ {
+ retval = ourstatus->value.related_pid = fake_create_process ();
+ saw_create++;
+ }
+ break;
+ }
/* Record the existence of this thread */
th = child_add_thread (current_event.dwThreadId,
current_event.u.CreateThread.hThread);
@@ -1245,8 +1273,6 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"EXIT_THREAD_DEBUG_EVENT"));
- if (saw_create != 1)
- break;
if (current_event.dwThreadId != main_thread_id)
{
child_delete_thread (current_event.dwThreadId);
@@ -1355,8 +1381,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
CHECK (child_continue (continue_status, -1));
else
{
- current_thread = th ? : thread_rec (current_event.dwThreadId, TRUE);
inferior_ptid = pid_to_ptid (retval);
+ current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
}
out:
@@ -1571,10 +1597,9 @@ child_attach (char *args, int from_tty)
}
if (has_detach_ability ())
- {
- attach_flag = 1;
- DebugSetProcessKillOnExit (FALSE);
- }
+ DebugSetProcessKillOnExit (FALSE);
+
+ attach_flag = 1;
if (from_tty)
{
@@ -1696,6 +1721,8 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
if (new_console)
flags |= CREATE_NEW_CONSOLE;
+ attach_flag = 0;
+
args = alloca (strlen (toexec) + strlen (allargs) + 2);
strcpy (args, toexec);
strcat (args, " ");
@@ -1897,7 +1924,8 @@ child_kill_inferior (void)
CHECK (CloseHandle (current_process_handle));
/* this may fail in an attached process so don't check. */
- (void) CloseHandle (current_thread->h);
+ if (current_thread && current_thread->h)
+ (void) CloseHandle (current_thread->h);
target_mourn_inferior (); /* or just child_mourn_inferior? */
}
@@ -2149,7 +2177,6 @@ cygwin_get_dr6 (void)
return dr[6];
}
-
/* Determine if the thread referenced by "pid" is alive
by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
it means that the pid has died. Otherwise it is assumed to be alive. */
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index c29bcc0..c28e26a 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -108,6 +108,7 @@ typedef struct thread_info_struct
HANDLE h;
char *name;
int suspend_count;
+ int reload_context;
CONTEXT context;
STACKFRAME sf;
}
@@ -228,7 +229,6 @@ check (BOOL ok, const char *file, int line)
GetLastError ());
}
-
/* Find a thread record given a thread id.
If get_context then also retrieve the context for this
thread. */
@@ -246,19 +246,7 @@ thread_rec (DWORD id, int get_context)
th->suspend_count = SuspendThread (th->h) + 1;
else if (get_context < 0)
th->suspend_count = -1;
-
- th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
- GetThreadContext (th->h, &th->context);
- if (id == current_event.dwThreadId)
- {
- /* Copy dr values from that thread. */
- dr[0] = th->context.Dr0;
- dr[1] = th->context.Dr1;
- dr[2] = th->context.Dr2;
- dr[3] = th->context.Dr3;
- dr[6] = th->context.Dr6;
- dr[7] = th->context.Dr7;
- }
+ th->reload_context = 1;
}
return th;
}
@@ -349,6 +337,24 @@ do_child_fetch_inferior_registers (int r)
char *context_offset = ((char *) &current_thread->context) + mappings[r];
long l;
+ if (!current_thread)
+ return;
+
+ if (current_thread->reload_context)
+ {
+ thread_info *th = current_thread;
+ th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+ GetThreadContext (th->h, &th->context);
+ /* Copy dr values from that thread. */
+ dr[0] = th->context.Dr0;
+ dr[1] = th->context.Dr1;
+ dr[2] = th->context.Dr2;
+ dr[3] = th->context.Dr3;
+ dr[6] = th->context.Dr6;
+ dr[7] = th->context.Dr7;
+ current_thread->reload_context = 0;
+ }
+
#define I387_ST0_REGNUM I386_ST0_REGNUM
if (r == I387_FISEG_REGNUM)
@@ -376,13 +382,16 @@ static void
child_fetch_inferior_registers (int r)
{
current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
- do_child_fetch_inferior_registers (r);
+ if (current_thread)
+ do_child_fetch_inferior_registers (r);
}
static void
do_child_store_inferior_registers (int r)
{
- if (r >= 0)
+ if (!current_thread)
+ /* nothing to do */;
+ else if (r >= 0)
regcache_collect (r, ((char *) &current_thread->context) + mappings[r]);
else
{
@@ -396,7 +405,8 @@ static void
child_store_inferior_registers (int r)
{
current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
- do_child_store_inferior_registers (r);
+ if (current_thread)
+ do_child_store_inferior_registers (r);
}
static int psapi_loaded = 0;
@@ -1179,7 +1189,7 @@ child_continue (DWORD continue_status, int id)
th->suspend_count = 0;
if (debug_registers_changed)
{
- /* Only change the value of the debug reisters */
+ /* Only change the value of the debug registers */
th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
th->context.Dr0 = dr[0];
th->context.Dr1 = dr[1];
@@ -1197,6 +1207,17 @@ child_continue (DWORD continue_status, int id)
return res;
}
+DWORD
+fake_create_process ()
+{
+ current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
+ current_event.dwProcessId);
+ main_thread_id = current_event.dwThreadId;
+ current_thread = child_add_thread (main_thread_id,
+ current_event.u.CreateThread.hThread);
+ return main_thread_id;
+}
+
/* Get the next event from the child. Return 1 if the event requires
handling by WFI (or whatever).
*/
@@ -1229,7 +1250,14 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
(unsigned) current_event.dwThreadId,
"CREATE_THREAD_DEBUG_EVENT"));
if (saw_create != 1)
- break;
+ {
+ if (!saw_create && attach_flag)
+ {
+ retval = ourstatus->value.related_pid = fake_create_process ();
+ saw_create++;
+ }
+ break;
+ }
/* Record the existence of this thread */
th = child_add_thread (current_event.dwThreadId,
current_event.u.CreateThread.hThread);
@@ -1245,8 +1273,6 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"EXIT_THREAD_DEBUG_EVENT"));
- if (saw_create != 1)
- break;
if (current_event.dwThreadId != main_thread_id)
{
child_delete_thread (current_event.dwThreadId);
@@ -1355,8 +1381,8 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
CHECK (child_continue (continue_status, -1));
else
{
- current_thread = th ? : thread_rec (current_event.dwThreadId, TRUE);
inferior_ptid = pid_to_ptid (retval);
+ current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
}
out:
@@ -1571,10 +1597,9 @@ child_attach (char *args, int from_tty)
}
if (has_detach_ability ())
- {
- attach_flag = 1;
- DebugSetProcessKillOnExit (FALSE);
- }
+ DebugSetProcessKillOnExit (FALSE);
+
+ attach_flag = 1;
if (from_tty)
{
@@ -1696,6 +1721,8 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
if (new_console)
flags |= CREATE_NEW_CONSOLE;
+ attach_flag = 0;
+
args = alloca (strlen (toexec) + strlen (allargs) + 2);
strcpy (args, toexec);
strcat (args, " ");
@@ -1897,7 +1924,8 @@ child_kill_inferior (void)
CHECK (CloseHandle (current_process_handle));
/* this may fail in an attached process so don't check. */
- (void) CloseHandle (current_thread->h);
+ if (current_thread && current_thread->h)
+ (void) CloseHandle (current_thread->h);
target_mourn_inferior (); /* or just child_mourn_inferior? */
}
@@ -2149,7 +2177,6 @@ cygwin_get_dr6 (void)
return dr[6];
}
-
/* Determine if the thread referenced by "pid" is alive
by "polling" it. If WaitForSingleObject returns WAIT_OBJECT_0
it means that the pid has died. Otherwise it is assumed to be alive. */