]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Show CONTEXT_EXCEPTION_REQUEST info in "info threads" (submit separately) (WIP)
authorPedro Alves <pedro@palves.net>
Mon, 12 Jun 2023 18:07:30 +0000 (19:07 +0100)
committerPedro Alves <pedro@palves.net>
Mon, 9 Jun 2025 17:09:18 +0000 (18:09 +0100)
document CONTEXT_EXCEPTION_REQUEST / CONTEXT_EXCEPTION_REPORTING /
   CONTEXT_EXCEPTION_ACTIVE / CONTEXT_SERVICE_ACTIVE.

    "so interesting... so I've been looking at only remaining testsuite
    hang that I saw in my last testsuite run.  it's a test that enables
    schedlock, and then calls a function in each thread in the program.
    on cygwin, the infcalls hang, and things break down such that the
    testcase ends up hanging forever.  back to the infcall hanging -- the
    issue is calling a function in a thread that is currently running
    kernel code.  on linux, most system calls are interruptible, and then
    syscall restart is a thing.  on Windows, system calls are NOT
    interruptible.  The threads in question in the testcase are stopped
    inside the syscall done by ntdll!ZwWaitForMultipleObjects .  I can
    pause the hung thread with ctrl-c, and its (userspace) PC won't have
    changed, still pointing to the entry to the function GDB wants to
    call.  Now, I remembered from reading about SuspendThread and
    GetThreadContext woes that there was a way to tell whether the
    interrupted thread was running kernel or userspace code.  After
    digging through my bookmarks, I found it.  It's explained here, in a
    comment from 2014 on a blog from 2010:

      https://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html#c5639760895973344002

    other places around the interwebs that I see with
    CONTEXT_EXCEPTION_REQUEST references all point to that sole comment...
    Microsoft doesn't document these flags, AFAICT.  Kind of funny.

    not sure what to do with that.  Maybe we could add a warning whenever
    GDB changes register contents of a thread blocked inside a syscall.
    For now, I'll just see if I can avoid the issue / hang in the test
    itself.

    "interesting -- I tried the same with visual studio, and it
     doesn't prevent evaluating the expression -- a dialog pops up
     saying something like "evaluating expression", and then after a few
     seconds it aborts it, with the result being the above.

     a time out for function calls sounds like a good idea to me.  I
     think lldb has one."

   At:
     https://learn.microsoft.com/en-us/visualstudio/debugger/error-evaluating-the-function-function-timed-out-and-needed-to-be-aborted-in-an-unsafe-way?view=vs-2022

     "One common reason for this problem is that when the debugger
     evaluates a property, it only allows the thread being inspected to
     execute. So if the property is waiting on other threads to run
     inside the debugged application, and if it is waiting in a way that
     the .NET Runtime isn't able to interrupt, this problem will
     happen."

Change-Id: I04221f123eef81d59b5cc1c9fbb298f7a33fa001

gdb/nat/windows-nat.h
gdb/windows-nat.c

index 568c7c46a5136b10857b084bdad839be9b175bf2..2d3fc3f8531cd58e9d10b1926fe370e5bae4c0d6 100644 (file)
@@ -524,7 +524,9 @@ struct WindowsContext<CONTEXT *>
                                     | CONTEXT_FLOATING_POINT
                                     | CONTEXT_SEGMENTS
                                     | CONTEXT_DEBUG_REGISTERS
-                                    | CONTEXT_EXTENDED_REGISTERS);
+                                    | CONTEXT_EXTENDED_REGISTERS
+                                    /* What about WoW64? */
+                                    | CONTEXT_EXCEPTION_REQUEST);
 };
 
 #ifdef __x86_64__
index 827f342f7fb2c04c118c94b79f44a3130bcca2b8..60521e60a8dd928ce101e65c38ca401078582897 100644 (file)
@@ -4110,6 +4110,17 @@ windows_nat_target::extra_thread_info (thread_info *info)
           || th->last_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
     return "exiting process";
 
+  /* FIXME: Wow64? */
+  windows_process.fill_thread_context (th);
+
+  if ((th->context.ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0)
+    {
+      if ((th->context.ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0)
+       return "in exception";
+      if ((th->context.ContextFlags & CONTEXT_SERVICE_ACTIVE) != 0)
+       return "in kernel";
+    }
+
   return nullptr;
 }