Change `self.build(...)` to assert if called with arguments of any kind,
for tests which have `SHARED_BUILD_TESTCASE` enabled (the default).
This also changes all tests that began asserting with this change, tests
which call `self.build(...)` with arguments.
---------
Co-authored-by: Adrian Prantl <adrian.prantl@gmail.com>
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads. This is a common scenario for hot breakpoints in
multithreaded programs and scales poorly.
This patch batches the step-over so that all threads at the same
breakpoint site are stepped together in a single vCont packet, with the
breakpoint disabled once at the start and re-enabled once after the last
thread finishes.
At the top of WillResume, any leftover StepOverBreakpoint plans from a
previous cycle are popped with their re-enable side effect suppressed
via SetReenabledBreakpointSite, giving a clean slate.
SetupToStepOverBreakpointIfNeeded then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through SetDeferReenableBreakpointSite. Instead of re-enabling
the breakpoint directly when a plan completes, it calls
ThreadFinishedSteppingOverBreakpoint, which decrements a per-address
tracking count. The breakpoint is only re-enabled when the count reaches
zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
For 10 threads at the same breakpoint, this reduces the operation from
10 z0/Z0 pairs and 10 vCont packets to 1 z0 + 1 Z0 and a few
progressively smaller batched vCont packets.
EDIT:
Tried to merge this PR twice, the first time the test was flaky so we
had to revert. The second time, we broke 2 tests on windows machine:
https://lab.llvm.org/buildbot/#/builders/141/builds/15798
The tests that were failing were failing because the cleanup code in
`WillResume` was popping **ALL** `StepOverBreakpoint` plans, including
non-deferred ones from incomplete single-steps.
The issue was:
1) Multiple threads hit the same breakpoint. One thread's breakpoint
condition evaluates to false, so it needs to auto-continue.
2) A `StepOverBreakpoint` plan is created for that thread
(non-deferred).
3) On the next WillResume, the cleanup pops that non-deferred plan.
4) Now the `StopOthers` scan finds no thread with a StopOthers() plan,
so thread_to_run stays null.
5) The else branch runs, calling `SetupToStepOverBreakpointIfNeeded` on
**ALL** threads, including the thread that legitimately hit the
breakpoint with a true condition.
6) That thread gets a new `StepOverBreakpoint` plan pushed, which
overwrites its breakpoint stop reason with trace when the step
completes.
The error `trace (2) != breakpoint (3)` confirms this, the thread that
should have reported breakpoint as its stop reason instead reports
trace, because an unwanted `StepOverBreakpoint` plan was pushed on it
and completed.
The newly added code fixes it by only popping plans that have
`GetDeferReenableBreakpointSite() == true`
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
Re-land https://github.com/llvm/llvm-project/pull/180101 since it was
reverted here https://github.com/llvm/llvm-project/pull/182431 because
of a flaky test. This PR include the modified test that should pass from
https://github.com/llvm/llvm-project/pull/182415 :
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads. This is a common scenario for hot breakpoints in
multithreaded programs and scales poorly.
This patch batches the step-over so that all threads at the same
breakpoint site are stepped together in a single vCont packet, with the
breakpoint disabled once at the start and re-enabled once after the last
thread finishes.
At the top of WillResume, any leftover StepOverBreakpoint plans from a
previous cycle are popped with their re-enable side effect suppressed
via SetReenabledBreakpointSite, giving a clean slate.
SetupToStepOverBreakpointIfNeeded then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through SetDeferReenableBreakpointSite. Instead of re-enabling
the breakpoint directly when a plan completes, it calls
ThreadFinishedSteppingOverBreakpoint, which decrements a per-address
tracking count. The breakpoint is only re-enabled when the count reaches
zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
For 10 threads at the same breakpoint, this reduces the operation from
10 z0/Z0 pairs and 10 vCont packets to 1 z0 + 1 Z0 and a few
progressively smaller batched vCont packets.
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
PR to fix failing test from
https://github.com/llvm/llvm-project/pull/180101 .
Fix the integration test to be resilient to non-deterministic thread
timing. Instead of requiring exact z0/Z0 counts, verify that batching
reduced toggles compared to one at a time stepping.
Also added: skip on `aarch64` where thread scheduling makes batching
unreliable.
Ran the test 20 times, passed all 20.
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
Following up from
https://discourse.llvm.org/t/improving-performance-of-multiple-threads-stepping-over-the-same-breakpoint/89637
When multiple threads are stopped at the same breakpoint, LLDB currently
steps each thread over the breakpoint one at a time. Each step requires
disabling the breakpoint, single-stepping one thread, and re-enabling
it, resulting in N disable/enable cycles and N individual vCont packets
for N threads.
Now we batch the step-over so that all threads at the same breakpoint
site are stepped together in a single vCont packet, with the breakpoint
disabled once at the start and re-enabled once after the last thread
finishes.
When we hit `WillResume` any leftover `StepOverBreakpoint` plans from a
previous cycle are popped with their re-enable side effect suppressed
via `SetReenabledBreakpointSite`, giving a clean slate.
`SetupToStepOverBreakpointIfNeeded` then creates fresh plans for all
threads that still need to step over a breakpoint, and these are grouped
by breakpoint address.
For groups with multiple threads, each plan is set to defer its
re-enable through `SetDeferReenableBreakpointSite`. Instead of
re-enabling the breakpoint directly when a plan completes, it calls
`ThreadFinishedSteppingOverBreakpoint`, which decrements a tracking
count per address. The breakpoint is only re-enabled when the count
reaches zero.
All threads in the largest group are resumed together in a single
batched vCont packet. If some threads don't complete their step in one
cycle, the pop-and-recreate logic naturally re-batches the remaining
threads on the next WillResume call.
Claude AI assisted in syntex fixes and making the comments more
understandable.
---------
Co-authored-by: Bar Soloveychik <barsolo@fb.com>
This changes Python API tests to use a single build shared across all
test functions, instead of the previous default behavior of a separate
build dir for each test function.
This build behavior opt-out, tests can use the previous behavior of one
individual (unshared) build directory per test function, by setting
`SHARED_BUILD_TESTCASE` to False (in the test class).
The motivation is to make the test suite more efficient, by not
repeatedly building the same test source. When running tests on my macOS
machine, this reduces the time of `ninja check-lldb-api` by almost 60%
(sample numbers: from ~492s down to ~207s = 58%). Almost 5min time
saved.
Each test function still calls `self.build()`, but only the first call
will do a build, in the subsequent tests `make` will be a no-op because
the sources won't have changed.
After #167359 / 95db31e7f69e7008f0c570ed30d54d1e418e10f2.
A fix was attempted in #167423 but was not quite enough.
From what I could understand, in v1 format you have to specify
all the basic blocks. Where before !call_me implied they were all
cold (I think, very shaky understanding here).
For this test we want to see blocks like call_me/foo/call_me.
So adding a line for block 1 fixes the tests.
It could produce more blocks at some point but I think as long
as foo is within two of them, it'll be fine.
The test did not work as intended when the empty function `done()`
contained prologue/epilogue code, because a breakpoint was set before
the last instruction of the function, which caused the test to pass even
with the fix from #126838 having been reverted.
The test is intended to check a case when a breakpoint is set on a
return instruction, which is the very last instruction of a function.
When stepping out from this breakpoint, there is interaction between
`ThreadPlanStepOut` and `ThreadPlanStepOverBreakpoint` that could lead
to missing the stop location in the outer frame; the detailed
explanation can be found in #126838.
On `Linux/AArch64`, the source is compiled into:
```
> objdump -d main.o
0000000000000000 <done>:
0: d65f03c0 ret
```
So, when the command `bt set -n done` from the original test sets a
breakpoint to the first instruction of `done()`, this instruction
luckily also happens to be the last one.
On `Linux/x86_64`, it compiles into:
```
> objdump -d main.o
0000000000000000 <done>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 5d pop %rbp
5: c3 ret
```
In this case, setting a breakpoint by function name means setting it
several instructions before `ret`, which does not provoke the
interaction between `ThreadPlanStepOut` and
`ThreadPlanStepOverBreakpoint`.
When a thread reaches a breakpoint at the return address set by
`ThreadPlanStepOut`, `ThreadPlanStepOut::ShouldStop()` calls
`ThreadPlanShouldStopHere::InvokeShouldStopHereCallback()`, and if it
returns `false`, `ThreadPlanShouldStopHere::QueueStepOutFromHerePlan()`
is called to queue a new plan to skip the corresponding range. Once the
new plan finishes, `ThreadPlanStepOut::ShouldStop()` should recheck the
stop condition; however, there is no code path in the method that sets
`done` to `true`. Before #126838, if `done` was `false`, the method checked
if a suitable frame had been reached. After the patch, the check is only
performed at a breakpoint; thus, the execution continues.
This patch causes `ThreadPlanStepOut::ShouldStop()` to recheck the stop
condition when `m_step_out_further_plan_sp` completes.
`INSERT BEFORE` keyword is not supported in current versions gold and
mold linkers. Since we cannot confirm accurately what linker and version
is available on the system and when it will be supported. We test it
with a sample program using the script keywords.
Failing on the macOS matrix bot for Clang-15 with the following error:
```
07:16:08 FAIL: LLDB (/Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/clang_1501_build/bin/clang-arm64) :: test_jump_offset_dwarf (TestThreadJump.ThreadJumpTestCase)
07:16:08 UNSUPPORTED: LLDB (/Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/clang_1501_build/bin/clang-arm64) :: test_jump_offset_dwo (TestThreadJump.ThreadJumpTestCase) (test case does not fall in any category of interest for this run)
07:16:08 Restore dir to: /Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/lldb-build/tools/lldb/test
07:16:08 ======================================================================
07:16:08 FAIL: test_jump_offset_dsym (TestThreadJump.ThreadJumpTestCase)
07:16:08 Test Thread Jump by negative or positive offset
07:16:08 ----------------------------------------------------------------------
07:16:08 Traceback (most recent call last):
07:16:08 File "/Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
07:16:08 return attrvalue(self)
07:16:08 File "/Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/llvm-project/lldb/test/API/functionalities/thread/jump/TestThreadJump.py", line 112, in test_jump_offset
07:16:08 self.expect(f"print {var_2}", substrs=[var_2_value])
07:16:08 File "/Users/ec2-user/jenkins/workspace/llvm.org/lldb-cmake-matrix/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2512, in expect
07:16:08 self.fail(log_msg)
07:16:08 AssertionError: Ran command:
07:16:08 "print var_2"
07:16:08
07:16:08 Got output:
07:16:08 (int) 20
07:16:08
07:16:08 Expecting sub string: "40" (was not found)
```
Fixes#45326
When you thread jump by calling
`j +2` or `thread jump --by +2` the offset is not recognised. This
commit fixes that.
---------
Signed-off-by: Ebuka Ezike <yerimyah1@gmail.com>
The architectures provided to skipIf / expectedFail are regular
expressions (v. _match_decorator_property() in decorators.py
so on Darwin systems "arm64" would match the skips for "arm" (32-bit
Linux). Update these to "arm$" to prevent this, and also update
three tests (TestBuiltinFormats.py, TestCrossDSOTailCalls.py,
TestCrossObjectTailCalls.py) that were skipped for arm64 via this
behavior, and need to be skipped or they will fail.
This was moviated by the new TestDynamicValue.py test which has
an expected-fail for arm, but the test was passing on arm64 Darwin
resulting in failure for the CIs.
test_common is force-included into every compilation, which causes
problems when we're compiling assembly code, as we were in #138805.
This avoids that as we can include the header only when it's needed.
The implementation has an optimization which detects the range of line
table entries covered by the function and then only searches for a
matching line between them.
This optimization was interfering with the logic for detecting whether a
line belongs to the function because the first call to FindLineEntry was
made with exact=false, which meant that if the function did not contain
any exact matches, we would just pick the closest line number in that
range, even if it was very far away.
This patch fixes that by first attempting an inexact search across the
entire line table, and then use the (potentially inexact) result of that
for searching within the function. This makes the optimization a less
effective, but I don't think we can differentiate between a line that
belongs to the function (but doesn't have any code) and a line outside
the function without that.
The patch also avoids the use of (deprecated) Function::GetAddressRange
by iterating over the GetAddressRanges result to find the full range of
line entries for the function.
I will be changing breakpoint hitting behavior soon, where currently
lldb reports a breakpoint as being hit when a thread is *at* a
BreakpointSite, but possibly has not executed the breakpoint instruction
and trapped yet, to having lldb only report a breakpoint hit when the
breakpoint instruction has actually been executed.
One corner case bug with this change is that when you are stopped at a
breakpoint (that has been hit) on the last instruction of a function,
and you do `finish`, a ThreadPlanStepOut is pushed to the thread's plan
stack to put a breakpoint on the return address and resume execution.
And when the thread is asked to resume, it sees that it is at a
BreakpointSite that has been hit, and pushes a
ThreadPlanStepOverBreakpoint on the thread. The StepOverBreakpoint
plan sees that the thread's state is eStateRunning (not eStateStepping),
so it marks itself as "auto continue" -- so once the breakpoint has
been stepped over, we will execution on the thread.
With current lldb stepping behavior ("a thread *at* a BreakpointSite is
said to have stopped with a breakpoint-hit stop reason, even if the
breakpoint hasn't been executed yet"),
`ThreadPlanStepOverBreakpoint::DoPlanExplainsStop` has a special bit of
code which detects when the thread stops with a eStopReasonBreakpoint.
It first checks if the pc is the same as when we started -- did our
"step instruction" not actually step? -- says the stop reason is
explained. Otherwise it sets auto-continue to false (because we've hit
an *unexpected* breakpoint, and we have advanced past our original pc,
and returns false - the stop reason is not explained.
So we do the "finish", lldb instruction steps, we stop *at* the
return-address breakpoint and lldb sets the thread's stop reason to
breakpoint-hit. ThreadPlanStepOverBreakpoint sees an
eStopReasonBreakpoint, sets its auto-continue to false, and says we
stopped for osme reason other than this plan. (and it will also report
`IsPlanStale()==true` so it will remove itself) Meanwhile the
ThreadPlanStepOut sees that it has stopped in the StackID it wanted to
run to, and return success.
This all changes when stopping at a breakpoint site doesn't report
breakpoint-hit until we actually execute the instruction. Now the
ThraedPlanStepOverBreakpoint looks at the thread's stop reason, it's
eStopReasonTrace (we've instruction stepped), and so it leaves its
auto-continue to `true`. ThreadPlanStepOut sees that it has reached its
goal StackID, removes its breakpoint, and says it is done.
Thread::ShouldStop thinks the auto-continue == yes vote from
ThreadPlanStepOverBreakpoint wins, and we lose control of the process.
This patch changes ThreadPlanStepOut to require that *both* (1) we are
at the StackID of the caller function, where we wanted to end up, and
(2) we have actually hit the breakpoint that we inserted.
This in effect means that now lldb instruction-steps over the breakpoint
in the callee function, stops at the return address of the caller
function. StepOverBreakpoint has completed. StepOut is still running,
and we continue the thread again. We immediatley hit the breakpoint
(that we're sitting at), and now ThreadPlanStepOut marks itself as
completed, and we return control to the user.
Jim suggests that ThreadPlanStepOverBreakpoint is a bit unusual because
it's not something pushed on the stack by a higher-order thread plan
that "owns" it, it is inserted by the Thread as it is about to resume,
if we're at a BreakpointSite. It has no connection to the thread plans
above it, but tries to set the auto-continue mode based on the state of
the thread when it is inserted (and tries to detect an unexpected
breakpoint and unset that auto-continue it previously decided on,
because it now realizes it should not influence execution control any
more). Instead maybe the
ThreadPlanStepOverBreakpoint should be inserted as a child plan of
whatever the lowest plan is on the stack at the point it is added.
I added an API test that will catch this bug in the new thread
breakpoint algorithm.
When a test depends on a new debugserver feature/fix, the API test must
be marked @skipIfOutOfTreeDebugserver because the macOS CI bots test
using the latest Xcode release debugserver. But over time all of these
fixes & new features are picked up in the Xcode debugserver and these
skips can be removed.
We may see unexpected test failures from removing all of these 1+ year
old skips, but that's likely a separate reason the test is failing that
is being papered over by this skip.
I think the only issue here was that we would erroneously consider
functions which are "in the middle" of the function were stepping to as
a part of the function, and would try to step into them (likely stepping
out of the function instead) instead of giving up early.
A lot of `TestConcurrent*.py` expect one of the threads to crash, but we
weren't checking for it properly.
Possibly because signal reporting got better on FreeBSD at some point,
and it now shows the same info as Linux does.
```
lldb-api :: functionalities/inferior-changed/TestInferiorChanged.py
lldb-api :: functionalities/inferior-crashing/TestInferiorCrashing.py
lldb-api :: functionalities/inferior-crashing/TestInferiorCrashingStep.py
lldb-api :: functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py
lldb-api :: functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferiorStep.py
lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py
lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py
lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py
lldb-api :: functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py
```
Fixes#48777
`TestConcurrentTwoBreakpointsOneSignal.py` no longer fails, at least on
an AWS instance, so I've removed the xfail there.
self.wait_for_running_event(process) is always called after
self.runCmd("continue"). It is strange to expect eStateConnected here.
This test failed in case of a remote target. The correct state is
eStateRunning. Removed incorrect checking.
This actually passes on Windows but I don't know how to convey
that with an xfail without clashing with the xfail for all
platforms.
At least this avoids a UPASS.
Any time we see the pattern `assertEqual(value, bool)`, we can replace
that with `assert<bool>(value)`. Likewise for `assertNotEqual`.
Technically this relaxes the test a bit, as we may want to make sure
`value` is either `True` or `False`, and not something that implicitly
converts to a bool. For example, `assertEqual("foo", True)` will fail,
but `assertTrue("foo")` will not. In most cases, this distinction is not
important.
There are two such places that this patch does **not** transform, since
it seems intentional that we want the result to be a bool:
*
5daf2001a1/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py (L90)
*
5daf2001a1/lldb/test/API/commands/settings/TestSettings.py (L940)
Followup to 9c2468821ec51defd09c246fea4a47886fff8c01. I patched `teyit`
with a `visit_assertEqual` node handler to generate this.
This uses [teyit](https://pypi.org/project/teyit/) to modernize asserts,
as recommended by the [unittest release
notes](https://docs.python.org/3.12/whatsnew/3.12.html#id3).
For example, `assertTrue(a == b)` is replaced with `assertEqual(a, b)`.
This produces better error messages, e.g. `error: unexpectedly found 1
and 2 to be different` instead of `error: False`.
assertEquals is a deprecated alias for assertEqual and has been removed
in Python 3.12. This wasn't an issue previously because we used a
vendored version of the unittest module. Now that we use the built-in
version this gets updated together with the Python version used to run
the test suite.
This removes the dependency LLDB API tests have on
lldb/third_party/Python/module/unittest2, and instead uses the standard
one provided by Python.
This does not actually remove the vendored dep yet, nor update the docs.
I'll do both those once this sticks.
Non-trivial changes to call out:
- expected failures (i.e. "bugnumber") don't have a reason anymore, so
those params were removed
- `assertItemsEqual` is now called `assertCountEqual`
- When a test is marked xfail, our copy of unittest2 considers failures
during teardown to be OK, but modern unittest does not. See
TestThreadLocal.py. (Very likely could be a real bug/leak).
- Our copy of unittest2 was patched to print all test results, even ones
that don't happen, e.g. `(5 passes, 0 failures, 1 errors, 0 skipped,
...)`, but standard unittest prints a terser message that omits test
result types that didn't happen, e.g. `OK (skipped=1)`. Our lit
integration parses this stderr and needs to be updated w/ that
expectation.
I tested this w/ `ninja check-lldb-api` on Linux. There's a good chance
non-Linux tests have similar quirks, but I'm not able to uncover those.
This is an ongoing series of commits that are reformatting our Python
code. Reformatting is done with `black` (23.1.0).
If you end up having problems merging this commit because you have made
changes to a python file, the best way to handle that is to run `git
checkout --ours <yourfile>` and then reformat it with black.
RFC: https://discourse.llvm.org/t/rfc-document-and-standardize-python-code-style
Differential revision: https://reviews.llvm.org/D151460
After D133376, jumping to the return line in the otherfn function became
ambiguous because it has two line entries associated with it. Work
around that problem by changing the function. Filed PR59458 to track
possible improvements in jump target disambiguation.
This commit combines the initial commit (7c240de609af), a fix for x86_64 Linux
(3a0581501e76) and a fix for thinko in a last minute rewrite that I really
should have run the testsuite on.
Also, make sure that all the "I need to step over watchpoint" plans execute
before we call a public stop. Otherwise, e.g. if you have N watchpoints and
a Signal, the signal stop info will get us to stop with the watchpoints in a
half-done state.
Differential Revision: https://reviews.llvm.org/D130674
Add a function to make it easier to debug a test failure caused by an
unexpected stop reason. This is similar to the assertState helper that
was added in ce825e46743b.
Before:
self.assertEqual(stop_reason, lldb.eStopReasonInstrumentation)
AssertionError: 5 != 10
After:
self.assertStopReason(stop_reason, lldb.eStopReasonInstrumentation)
AssertionError: signal (5) != instrumentation (10)
Differential revision: https://reviews.llvm.org/D131083
This reverts commit 5778ada8e54edb2bc2869505b88a959d1915c02f.
The watchpoint tests all stall on aarch64-ubuntu bots. Reverting till I can
get my hands on an system to test this out.
Since we want to present the "new & old" values for watchpoint hits, on architectures,
including the ARM family, that stop before the triggering instruction is run, we need
to single step over the instruction before stopping for realz. This was incorrectly
done directly in the StopInfoWatchpoint::ShouldStop. That causes problems if more than
one thread stops "for a reason" at the same time as the watchpoint, since the other actions
didn't expect the process to make progress in this part of the execution control machinery.
The correct way to do this is to schedule the step over using ThreadPlans, and then to restore
the stop info after that plan stops, so that the rest of the stop info actions can happen when
all the other threads have handled their immediate actions as well.
Differential Revision: https://reviews.llvm.org/D129814
The requirements for "thread until <line number>" are:
a) If any code contributed by <line number> or the nearest subsequent of <line number> is executed before leaving the function, stop
b) If you end up leaving the function w/o triggering (a), then stop
In case of (a), since the <line number> may have multiple entries in the line table and the compiler might have scheduled/moved the relevant code across, and the lldb does not know the control flow, set breakpoints on all the line table entries of best match of <line number> i.e. exact or the nearest subsequent line.
Along with the above, currently, CommandObjectThreadUntil is also setting the breakpoints on all the subsequent line numbers after the best match and this latter part is wrong.
This issue is discussed at http://lists.llvm.org/pipermail/lldb-dev/2018-August/013979.html.
In fact, currently `TestStepUntil.py` is not actually testing step until scenarios and `test_missing_one` test fails without this patch if tests are made to run. Fixed the test as well.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D50304
The requirements for "thread until <line number>" are:
a) If any code contributed by <line number> or the nearest subsequent of <line number> is executed before leaving the function, stop
b) If you end up leaving the function w/o triggering (a), then stop
In case of (a), since the <line number> may have multiple entries in the line table and the compiler might have scheduled/moved the relevant code across, and the lldb does not know the control flow, set breakpoints on all the line table entries of best match of <line number> i.e. exact or the nearest subsequent line.
Along with the above, currently, CommandObjectThreadUntil is also setting the breakpoints on all the subsequent line numbers after the best match and this latter part is wrong.
This issue is discussed at http://lists.llvm.org/pipermail/lldb-dev/2018-August/013979.html.
In fact, currently `TestStepUntil.py` is not actually testing step until scenarios and `test_missing_one` test fails without this patch if tests are made to run. Fixed the test as well.
Reviewed By: jingham
Differential Revision: https://reviews.llvm.org/D50304