public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
* [Bug gdb/32608] New: [gdb, -m32] FAIL: gdb.threads/step-over-thread-exit-while-stop-all-threads.exp: displaced-stepping=auto: target-non-stop=on: iter 8: continue
@ 2025-01-28 11:55 vries at gcc dot gnu.org
  2025-01-28 11:56 ` [Bug gdb/32608] " vries at gcc dot gnu.org
  0 siblings, 1 reply; 2+ messages in thread
From: vries at gcc dot gnu.org @ 2025-01-28 11:55 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=32608

            Bug ID: 32608
           Summary: [gdb, -m32] FAIL:
                    gdb.threads/step-over-thread-exit-while-stop-all-threa
                    ds.exp: displaced-stepping=auto: target-non-stop=on:
                    iter 8: continue
           Product: gdb
           Version: HEAD
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gdb
          Assignee: unassigned at sourceware dot org
          Reporter: vries at gcc dot gnu.org
  Target Milestone: ---

Created attachment 15902
  --> https://sourceware.org/bugzilla/attachment.cgi?id=15902&action=edit
gdb.log

I did the following experiment:
...
$ for n in $(seq 1 50); do \
    taskset -c 11 ./test.sh -m32 2>&1 \
    | grep "^# of " \
    | sort -u; cp gdb.log gdb.$n.log; \
  done
...
where test.sh -m32 runs test-case
gdb.threads/step-over-thread-exit-while-stop-all-threads.exp with target board
unix/-m32, and ran into this FAIL:
...
Thread 36 "step-over-threa" received signal SIGSEGV, Segmentation fault.^M
[Switching to Thread 0xe72e0b40 (LWP 29790)]^M
0x00000000 in ?? ()^M
(gdb) FAIL: gdb.threads/step-over-thread-exit-while-stop-all-threads.exp:
displaced-stepping=auto: target-non-stop=on: iter 8: continue
...

I then added:
...
diff --git
a/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
b/gdb/testsuite/gdb.threads/step-ove
r-thread-exit-while-stop-all-threads.exp
index d37c44f7c73..e0729f88508 100644
---
a/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
+++
b/gdb/testsuite/gdb.threads/step-over-thread-exit-while-stop-all-threads.exp
@@ -52,9 +52,12 @@ proc test {displaced-stepping target-non-stop} {
     # Make sure the target reports the breakpoint stops.
     gdb_test_no_output "set breakpoint condition-evaluation host"

+    gdb_test_no_output "set debug displaced on"
+    gdb_test_no_output "set debug infrun on"
+    
     for { set i 0 } { $i < 30 } { incr i } {
        with_test_prefix "iter $i" {
-           if { [gdb_test "continue" "hit Breakpoint $::decimal, break_here
.*"] != 0 } {
+           if { [gdb_test -no-prompt-anchor "continue" "hit Breakpoint
$::decimal, break_here .*"] != 0 } {
                # Exit if there's a failure to avoid lengthy timeouts.
                break
            }
...
and redid the experiment, gdb.log attached.

The series of relevant events is as follows, following thread LWP 29790.

We're executing the my_exit function, specifically the syscall instruction at
8048632:
...
08048621 <my_exit>:
 8048621:       b8 01 00 00 00          mov    $0x1,%eax
 8048626:       8b 5c 24 04             mov    0x4(%esp),%ebx
 804862a:       8b 4c 24 08             mov    0x8(%esp),%ecx
 804862e:       8b 54 24 0c             mov    0xc(%esp),%edx

08048632 <my_exit_syscall>:
 8048632:       cd 80                   int    $0x80
 8048634:       c3                      ret
...

And we're executing it using displaced stepping, which is setup here:
...
  [displaced] displaced_step_prepare_throw: displaced-stepping 29753.29790.0
now^M
  [displaced] displaced_step_prepare_throw: original insn 0x8048632: cd 80     
 int    $0x80^M
  [displaced] prepare: selected buffer at 0x8048402^M
  [displaced] prepare: saved 0x8048402: 5e 89 e1 83 e4 f0 50 54 52 e8 19 00 00
00 81 c3^M
  [displaced] i386_displaced_step_copy_insn: 0x8048632->0x8048402: cd 80 90 00
00 00 53 83 ec 08 e8 0f fe ff ff 81^M
  [displaced] displaced_step_prepare_throw: prepared successfully
thread=29753.29790.0, original_pc=0x8048632, displaced_pc=0x8048402^M
  [displaced] displaced_step_prepare_throw: replacement insn 0x8048402: cd 80  
 int    $0x80^M
...

So we copy the insn (0xcd 0x80) to a buffer at _start+0x2, with a nop added
(0x90).

Once it's setup, we do a PTRACE_SINGLESTEP:
...
  [infrun] do_target_resume: resume_ptid=29753.29790.0, step=1,
sig=GDB_SIGNAL_0^M
...

Then this happens:
...
    [infrun] stop_all_threads:   29753.29790.0 executing, need stop^M
...
which means that a SIGSTOP is sent to the thread.

And the stop happens:
...
    [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1],
status) =^M
    [infrun] print_target_wait_results:   29753.29790.0 [Thread 0xe72e0b40 (LWP
29790)],^M
    [infrun] print_target_wait_results:   status->kind = STOPPED, sig =
GDB_SIGNAL_0^M
    [infrun] handle_one: status->kind = STOPPED, sig = GDB_SIGNAL_0
29753.29790.0^M
...

Then the displaced stepping setup is reverted:
...
    [displaced] finish: restored 29753.29790.0 0x8048402^M
    [displaced] i386_displaced_step_fixup: fixup (0x8048632, 0x8048402), insn =
0xcd 0x80 ...^M
    [displaced] i386_displaced_step_fixup: syscall changed %eip; not
relocating^M
    [infrun] handle_one: displaced-step of 29753.29790.0 canceled^M
    [infrun] global_thread_step_over_chain_enqueue: enqueueing thread
29753.29790.0 in global step over chain^M
...

Here we see two interesting things:
- the instruction pointer has changed, and 
- the displaced-step is canceled.

The first is done here in i386_displaced_step_fixup:
...
      if (i386_syscall_p (insn, &insn_len)
          && pc != to + (insn - insn_start) + insn_len
          /* GDB can get control back after the insn after the syscall.         
             Presumably this is a kernel bug.                                   
             i386_displaced_step_copy_insn ensures it's a nop,                  
             we add one to the length for it.  */
          && pc != to + (insn - insn_start) + insn_len + 1)
        displaced_debug_printf ("syscall changed %%eip; not relocating");
...
and the second here in handle_one:
...
         if (displaced_step_finish (t, event.ws)
              == DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED)
            {
              /* Add it back to the step-over queue.  */
              infrun_debug_printf
                ("displaced-step of %s canceled",
                 t->ptid.to_string ().c_str ());

              t->control.trap_expected = 0;
              if (!t->inf->detaching)
                global_thread_step_over_chain_enqueue (t);
            }
...

Then we resume:
...
    [infrun] do_target_resume: resume_ptid=29753.29790.0, step=0,
sig=GDB_SIGNAL_0^M
...
and run into:
...
  [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status)
=^M
  [infrun] print_target_wait_results:   29753.29790.0 [Thread 0xe72e0b40 (LWP
29790)],^M
  [infrun] print_target_wait_results:   status->kind = STOPPED, sig =
GDB_SIGNAL_SEGV^M
  [infrun] handle_inferior_event: status->kind = STOPPED, sig =
GDB_SIGNAL_SEGV^M
...
at:
...
  [infrun] handle_signal_stop: stop_pc=0x0^M
  [infrun] handle_signal_stop: random signal (GDB_SIGNAL_SEGV)^M
...

So, AFAICT, this is a kernel bug, where the kernel overwrites the pc while it
shouldn't.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Bug gdb/32608] [gdb, -m32] FAIL: gdb.threads/step-over-thread-exit-while-stop-all-threads.exp: displaced-stepping=auto: target-non-stop=on: iter 8: continue
  2025-01-28 11:55 [Bug gdb/32608] New: [gdb, -m32] FAIL: gdb.threads/step-over-thread-exit-while-stop-all-threads.exp: displaced-stepping=auto: target-non-stop=on: iter 8: continue vries at gcc dot gnu.org
@ 2025-01-28 11:56 ` vries at gcc dot gnu.org
  0 siblings, 0 replies; 2+ messages in thread
From: vries at gcc dot gnu.org @ 2025-01-28 11:56 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=32608

--- Comment #1 from Tom de Vries <vries at gcc dot gnu.org> ---
Tentative patch:
...
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 4687ee6edb3..019a8653d9f 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5524,6 +5524,8 @@ handle_one (const wait_one_event &event)
                ("displaced-step of %s canceled",
                 t->ptid.to_string ().c_str ());

+             regcache_write_pc (get_thread_regcache (t), t->prev_pc);
+
              t->control.trap_expected = 0;
              if (!t->inf->detaching)
                global_thread_step_over_chain_enqueue (t);
...

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-01-28 11:56 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-28 11:55 [Bug gdb/32608] New: [gdb, -m32] FAIL: gdb.threads/step-over-thread-exit-while-stop-all-threads.exp: displaced-stepping=auto: target-non-stop=on: iter 8: continue vries at gcc dot gnu.org
2025-01-28 11:56 ` [Bug gdb/32608] " vries at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).