odd behavior when source stepping libcxx test - lldb thinks process is running, but never sent a step/resume

We’re porting libcxx to Hexagon. Stepping the first line in wait.pass.cpp will put lldb in a bad state – it thinks the target has resumed, but it never sends a step or resume packet to the remote gdbserver. Sometimes it will step part of the line, return control, then stepping again goes to the bad state.

The system has 4 threads; only thread 3 is currently being used. The bad state happens because ProcessGDBRemote::DoResume can’t figure out how to send a resume packet. During the thread plan it resumes all threads. Later it goes to step thread 3, but it also wants to resume threads 1,2,4, but our gdbserver doesn’t support vCont, so it gives up. I don’t think it should be resuming threads 1,2,4.

How can I fix this?

The source file is wait.pass.cpp: https://llvm.org/svn/llvm-project/libcxx/trunk/test/std/thread/thread.condition/thread.condition.condvar/wait.pass.cpp

Disassembly of line 43:

42 {

→ 43 std::unique_lockstd::mutexlk(mut);

44 std::thread t(f);

→ 0x10011c4 <+20>: { memw(r30+#-20) = r2 }

0x10011c8 <+24>: { immext(#18198784)

0x10011cc <+28>: r2 = ##18198784 }

0x10011d0 <+32>: { memw(r30+#-24) = r2 }

0x10011d4 <+36>: { r2 = memw(r30 + #-20) }

wait.pass.cpp.exe`main + 40 [inlined] std::__1::unique_lockstd::__1::mutex::unique_lock(std::__1::mutex&) at wait.pass.cpp:43

0x10011d8 <+40>: { r3 = memw(r30 + #-24) }

wait.pass.cpp.exe`main + 44 [inlined] std::__1::unique_lockstd::__1::mutex::unique_lock(std::__1::mutex&) + 4 at wait.pass.cpp:43

0x10011dc <+44>: { memw(r2+#0) = r3 }

wait.pass.cpp.exe`main + 48 [inlined] std::__1::unique_lockstd::__1::mutex::unique_lock(std::__1::mutex&) + 8 at wait.pass.cpp:43

0x10011e0 <+48>: { memb(r2+#4)=#1 }

wait.pass.cpp.exe`main + 52 [inlined] std::__1::unique_lockstd::__1::mutex::unique_lock(std::__1::mutex&) + 12 at wait.pass.cpp:43

0x10011e4 <+52>: { r0 = memw(r2 + #0) }

0x10011e8 <+56>: { call 0x1001ab4 } ; std::__1::mutex::lock at mutex.cpp:31

The only change-of-flow is the call instruction at the end.

Select linetable info, from llvm-dwarfdump:

Address Line Column File ISA Discriminator Flags


0x00000000010011c4 43 33 11 0 0 is_stmt prologue_end

0x00000000010011d8 112 17 3 0 0 is_stmt

0x00000000010011dc 112 11 3 0 0

0x00000000010011e0 112 23 3 0 0

0x00000000010011e4 112 38 3 0 0

0x00000000010011ec 44 17 11 0 0 is_stmt

File 11 is wait.pass.cpp; file 3 is __mutex_base, where the inlined std::unique_lock is defined.

Step log:

(lldb) r

Process 1 launched: ‘c:\lldb\test\cxx11\wait.pass.cpp.exe’ (hexagon)

Process 1 stopped

  • thread #3: tid = 0x0003, 0x010011c4 wait.pass.cpp.exe`main + 20 at wait.pass.cpp:43, stop reason = breakpoint 1.1

frame #0: 0x010011c4 wait.pass.cpp.exe`main + 20 at wait.pass.cpp:43

40

41 int main()

42 {

→ 43 std::unique_lockstd::mutexlk(mut);

44 std::thread t(f);

45 assert(test1 == 0);

46 while (test1 == 0) {

(lldb) thread list

Process 1 stopped

thread #1: tid = 0x0001, 0xff004f64

thread #2: tid = 0x0002, 0xff004f64

  • thread #3: tid = 0x0003, 0x010011c4 wait.pass.cpp.exe`main + 20 at wait.pass.cpp:43, stop reason = breakpoint 1.1

thread #4: tid = 0x0004, 0xff004f64

(lldb) log enable lldb step

(lldb) s

Finding branch index from address @ 0x010011c4

Instruction @0x010011C4 : 0xA79EE2FB

Packet start @0x010011C8

Instruction @0x010011C8 : 0x001156C4

Instruction @0x010011D0 : 0xA79EE2FA

Packet start @0x010011D4

Thread::PushPlan(0x0000000004E678D0): “Stepping in through line wait.pass.cpp:43.”, tid = 0x0003.

Process::PrivateResume() m_stop_id = 2, public state: stopped private state: stopped

Failed to create new thread notification breakpoint.

Thread::PushPlan(0x0000000004E678D0): “Single stepping past breakpoint site 2 at 0x10011c4”, tid = 0x0003.

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid = 0x0001, pc = 0xff004f64, sp = 0xff00cb78, fp = 0xff002d10, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011c4, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step over breakpoint trap’, state = stepping, stop others = 1

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0xff004f64, sp = 0xff00ce60, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

Current Plan for thread 1(00000000045DDE10) (0x0001, suspended): base plan being asked whether we should report run.

Current Plan for thread 2(0000000004E660B0) (0x0002, suspended): base plan being asked whether we should report run.

Current Plan for thread 3(0000000004E678D0) (0x0003, stepping): Step over breakpoint trap being asked whether we should report run.

Current Plan for thread 4(0000000004E69080) (0x0004, suspended): base plan being asked whether we should report run.

Process thinks the process has resumed.

(lldb) s

ThreadList::lldb_private::ThreadList::ShouldStop: 4 threads, 1 unsuspended threads

Thread::lldb_private::thread::ShouldStop for tid = 0x0003 0x0003, pc = 0x00000000010011c8, should_stop = 0 (ignore since no stop reason)

ThreadList::lldb_private::ThreadList::ShouldStop overall should_stop = 0ThreadList::lldb_private::ThreadList::ShouldReportStop 4 threads

Thread::ShouldReportStop() tid = 0x0001: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0002: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0003: returning vote 0 (thread didn’t stop for a reason.)

Thread::ShouldReportStop() tid = 0x0004: returning vote 0 (temporary state was suspended or invalid)

ThreadList::lldb_private::ThreadList::ShouldReportStop returning no opinionProcess::PrivateResume() m_stop_id = 3, public state: running private state: stopped

Failed to create new thread notification breakpoint.

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid = 0x0001, pc = 0x010011c8, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011c8, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step over breakpoint trap’, state = stepping, stop others = 1

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0xff004f64, sp = 0xff00ce60, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

Process thinks the process has resumed.

ThreadList::lldb_private::ThreadList::ShouldStop: 4 threads, 1 unsuspended threads

Thread::lldb_private::thread::ShouldStop for tid = 0x0003 0x0003, pc = 0x00000000010011d0, should_stop = 0 (ignore since no stop reason)

ThreadList::lldb_private::ThreadList::ShouldStop overall should_stop = 0ThreadList::lldb_private::ThreadList::ShouldReportStop 4 threads

Thread::ShouldReportStop() tid = 0x0001: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0002: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0003: returning vote 0 (thread didn’t stop for a reason.)

Thread::ShouldReportStop() tid = 0x0004: returning vote 0 (temporary state was suspended or invalid)

ThreadList::lldb_private::ThreadList::ShouldReportStop returning no opinion

Process::PrivateResume() m_stop_id = 4, public state: running private state: stopped

Failed to create new thread notification breakpoint.

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid = 0x0001, pc = 0xff004f64, sp = 0xff00cb78, fp = 0xff002d10, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011d0, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step over breakpoint trap’, state = stepping, stop others = 1

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0x010011d0, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘base plan’, state= suspended, stop others = 0

Process thinks the process has resumed.

ThreadList::lldb_private::ThreadList::ShouldStop: 4 threads, 1 unsuspended threads

Thread::lldb_private::thread::ShouldStop(0000000004E678D0) for tid = 0x0003 0x0003, pc = 0x00000000010011d4

^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^

Plan stack initial state:

thread #3: tid = 0x0003:

Active plan stack:

Element 0: Base thread plan.

Element 1: Stepping in through line wait.pass.cpp:43 using ranges:[0x010011c4-0x010011d8).

Element 2: Single stepping past breakpoint site 2 at 0x10011c4

Plan Step over breakpoint trap explains stop, auto-continue 0.

Plan Step over breakpoint trap should stop: 1.

Completed step over breakpoint plan.

Popping plan: “Step over breakpoint trap”, tid = 0x0003.

ThreadPlanStepInRange reached 0x010011d4.

Plan Step Range stepping in should stop: 0.

Plan stack final state:

thread #3: tid = 0x0003:

Active plan stack:

Element 0: Base thread plan.

Element 1: Stepping in through line wait.pass.cpp:43 using ranges:[0x010011c4-0x010011d8).

Completed Plan Stack:

Element 0: Single stepping past breakpoint site 2 at 0x10011c4

vvvvvvvv Thread::ShouldStop End (returning 0) vvvvvvvv

ThreadList::lldb_private::ThreadList::ShouldStop overall should_stop = 0

ThreadList::lldb_private::ThreadList::ShouldReportStop 4 threads

Thread::ShouldReportStop() tid = 0x0001: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0002: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0003: returning vote for complete stack’s back plan

ThreadPlan::ShouldReportStop() returning vote: no

Thread::ShouldReportStop() tid = 0x0004: returning vote 0 (temporary state was suspended or invalid)

ThreadList::lldb_private::ThreadList::ShouldReportStop returning no

Process::PrivateResume() m_stop_id = 5, public state: running private state: stopped

Failed to create new thread notification breakpoint.

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid = 0x0001, pc = 0xff004f64, sp = 0xff00cb78, fp = 0xff002d10, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011d4, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step Range stepping in’, state = stepping, stop others = 1

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0xff004f64, sp = 0xff00ce60, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

Process thinks the process has resumed.

ThreadList::lldb_private::ThreadList::ShouldStop: 4 threads, 1 unsuspended threads

Thread::lldb_private::thread::ShouldStop for tid = 0x0003 0x0003, pc = 0x00000000010011d8, should_stop = 0 (ignore since no stop reason)

ThreadList::lldb_private::ThreadList::ShouldStop overall should_stop = 0

ThreadList::lldb_private::ThreadList::ShouldReportStop 4 threads

Thread::ShouldReportStop() tid = 0x0001: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0002: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0003: returning vote 0 (thread didn’t stop for a reason.)

Thread::ShouldReportStop() tid = 0x0004: returning vote 0 (temporary state was suspended or invalid)

ThreadList::lldb_private::ThreadList::ShouldReportStop returning no opinion

Process::PrivateResume() m_stop_id = 6, public state: running private state: stopped

Failed to create new thread notification breakpoint.

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid= 0x0001, pc = 0xff004f64, sp = 0xff00cb78, fp = 0xff002d10, plan = ‘base plan’, state = suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= suspended, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011d8, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step Range stepping in’, state = stepping, stop others = 1

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0x010011d8, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘base plan’, state= suspended, stop others = 0

Process thinks the process has resumed.

ThreadList::lldb_private::ThreadList::ShouldStop: 4 threads, 1 unsuspended threads

Thread::lldb_private::thread::ShouldStop(0000000004E678D0) for tid = 0x0003 0x0003, pc = 0x00000000010011dc

^^^^^^^^ Thread::ShouldStop Begin ^^^^^^^^

Plan stack initial state:

thread #3: tid = 0x0003:

Active plan stack:

Element 0: Base thread plan.

Element 1: Stepping in through line wait.pass.cpp:43 using ranges:[0x010011c4-0x010011d8).

Plan Step Range stepping in explains stop, auto-continue 0.

ThreadPlanStepInRange reached 0x010011dc.

Couldn’t find step through plan from address 0x10011dc.

No step through plan found.

Stepping out of function “std::__1::unique_lockstd::__1::mutex::unique_lock(std::__1::mutex&)” because it matches the avoid regexp “^std::” - match substring: “std::”.

ShouldStopHere callback returned 0 from 0x10011dc.

Queuing inlined frame to step past: frame #0: 0x010011dc wait.pass.cpp.exemain+ 44 [inlined] std::__1::unique_lock<std::__1::mutex>::unique_lock(std::__1::mutex&) + 4 at wait.pass.cpp:43 wait.pass.cpp.exemain + 40 at wait.pass.cpp:43.

Finding branch index from address @ 0x010011dc

Instruction @0x010011DC : 0xA182C300

Packet start @0x010011E0

Instruction @0x010011E0 : 0x3C02C201

Packet start @0x010011E4

Instruction @0x010011E4 : 0x9182C000

Packet start @0x010011E8

Thread::PushPlan(0x0000000004E678D0): “Stepping over using ranges: [0x010011d8-0x010011ec).”, tid = 0x0003.

Thread::PushPlan(0x0000000004E678D0): “Stepping out by stepping through inlinedfunction.”, tid = 0x0003.

Plan Step Range stepping in should stop: 0.

Plan stack final state:

thread #3: tid = 0x0003:

Active plan stack:

Element 0: Base thread plan.

Element 1: Stepping in through line wait.pass.cpp:43 using ranges:[0x010011c4-0x010011d8).

Element 2: Stepping out by stepping through inlined function.

Element 3: Stepping over using ranges: [0x010011d8-0x010011ec).

vvvvvvvv Thread::ShouldStop End (returning 0) vvvvvvvv

ThreadList::lldb_private::ThreadList::ShouldStop overall should_stop = 0

ThreadList::lldb_private::ThreadList::ShouldReportStop 4 threads

Thread::ShouldReportStop() tid = 0x0001: returning vote 0 (temporary state was suspended or invalid)

Thread::ShouldReportStop() tid = 0x0002: returning vote 0 (temporary state was suspended or invalid)

ThreadPlanStepRange::ShouldReportStop() returning vote -1

Thread::ShouldReportStop() tid = 0x0003: returning vote -1 for current plan

Thread::ShouldReportStop() tid = 0x0004: returning vote 0 (temporary state was suspended or invalid)

ThreadList::lldb_private::ThreadList::ShouldReportStop returning no

Process::PrivateResume() m_stop_id = 7, public state: running private state: stopped

lldb_private::ThreadPlan::WillResume Thread #1 (0x00000000045DDE10): tid = 0x0001, pc = 0xff004f64, sp = 0xff00cb78, fp = 0xff002d10, plan = ‘base plan’, state= running, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #2 (0x0000000004E660B0): tid = 0x0002, pc = 0xff004f64, sp = 0xff00cc70, fp = 0x00000000, plan = ‘base plan’, state= running, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #3 (0x0000000004E678D0): tid = 0x0003, pc = 0x010011dc, sp = 0x0525eca8, fp = 0x0525ecf8, plan = ‘Step range stepping over’, state = stepping, stop others = 0

lldb_private::ThreadPlan::WillResume Thread #4 (0x0000000004E69080): tid = 0x0004, pc = 0xff004f64, sp = 0xff00ce60, fp = 0x00000000, plan = ‘base plan’, state= running, stop others = 0