-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial step in targets DAP support (#86623)
This patch provides the initial implementation for the "Step Into Specific/Step In Targets" feature in VSCode DAP. The implementation disassembles all the call instructions in step range and try to resolve operand name (assuming one operand) using debug info. Later, the call target function name is chosen by end user and specified in the StepInto() API call. It is v1 because of using the existing step in target function name API. This implementation has several limitations: * Won't for indirect/virtual function call -- in most cases, our disassembler won't be able to solve the indirect call target address/name. * Won't work for target function without debug info -- if the target function has symbol but not debug info, the existing ThreadPlanStepInRange won't stop. * Relying on function names can be fragile -- if there is some middle glue/thunk code, our disassembler can only resolve the glue/thunk code's name not the real target function name. It can be fragile to depend compiler/linker emits the same names for both. * Does not support step into raw address call sites -- it is a valid scenario that in Visual Studio debugger, user can explicitly choose a raw address to step into which land in the function without debug info/symbol, then choose UI to load the debug info on-demand for that module/frame to continue exploring. A more reliable design could be extending the ThreadPlanStepInRange to support step in based on call-site instruction offset/PC which I will propose in next iteration. --------- Co-authored-by: jeffreytan81 <jeffreytan@fb.com>
- Loading branch information
1 parent
02660e2
commit 2f2e31c
Showing
12 changed files
with
296 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
ENABLE_THREADS := YES | ||
|
||
CXX_SOURCES := main.cpp | ||
|
||
include Makefile.rules |
68 changes: 68 additions & 0 deletions
68
lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
""" | ||
Test lldb-dap stepInTargets request | ||
""" | ||
|
||
import dap_server | ||
from lldbsuite.test.decorators import * | ||
from lldbsuite.test.lldbtest import * | ||
import lldbdap_testcase | ||
from lldbsuite.test import lldbutil | ||
|
||
|
||
class TestDAP_stepInTargets(lldbdap_testcase.DAPTestCaseBase): | ||
@skipIf( | ||
archs=no_match(["x86_64"]) | ||
) # InstructionControlFlowKind for ARM is not supported yet. | ||
def test_basic(self): | ||
""" | ||
Tests the basic stepping in targets with directly calls. | ||
""" | ||
program = self.getBuildArtifact("a.out") | ||
self.build_and_launch(program) | ||
source = "main.cpp" | ||
|
||
breakpoint_line = line_number(source, "// set breakpoint here") | ||
lines = [breakpoint_line] | ||
# Set breakpoint in the thread function so we can step the threads | ||
breakpoint_ids = self.set_source_breakpoints(source, lines) | ||
self.assertEqual( | ||
len(breakpoint_ids), len(lines), "expect correct number of breakpoints" | ||
) | ||
self.continue_to_breakpoints(breakpoint_ids) | ||
|
||
threads = self.dap_server.get_threads() | ||
self.assertEqual(len(threads), 1, "expect one thread") | ||
tid = threads[0]["id"] | ||
|
||
leaf_frame = self.dap_server.get_stackFrame() | ||
self.assertIsNotNone(leaf_frame, "expect a leaf frame") | ||
|
||
# Request all step in targets list and verify the response. | ||
step_in_targets_response = self.dap_server.request_stepInTargets( | ||
leaf_frame["id"] | ||
) | ||
self.assertEqual(step_in_targets_response["success"], True, "expect success") | ||
self.assertIn( | ||
"body", step_in_targets_response, "expect body field in response body" | ||
) | ||
self.assertIn( | ||
"targets", | ||
step_in_targets_response["body"], | ||
"expect targets field in response body", | ||
) | ||
|
||
step_in_targets = step_in_targets_response["body"]["targets"] | ||
self.assertEqual(len(step_in_targets), 3, "expect 3 step in targets") | ||
|
||
# Verify the target names are correct. | ||
self.assertEqual(step_in_targets[0]["label"], "bar()", "expect bar()") | ||
self.assertEqual(step_in_targets[1]["label"], "bar2()", "expect bar2()") | ||
self.assertEqual( | ||
step_in_targets[2]["label"], "foo(int, int)", "expect foo(int, int)" | ||
) | ||
|
||
# Choose to step into second target and verify that we are in bar2() | ||
self.stepIn(threadId=tid, targetId=step_in_targets[1]["id"], waitForStop=True) | ||
leaf_frame = self.dap_server.get_stackFrame() | ||
self.assertIsNotNone(leaf_frame, "expect a leaf frame") | ||
self.assertEqual(leaf_frame["name"], "bar2()") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
|
||
int foo(int val, int extra) { return val + extra; } | ||
|
||
int bar() { return 22; } | ||
|
||
int bar2() { return 54; } | ||
|
||
int main(int argc, char const *argv[]) { | ||
foo(bar(), bar2()); // set breakpoint here | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.