[Lldb-commits] [lldb] Initial step in targets DAP support (PR #86623)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Mar 27 14:34:59 PDT 2024
================
@@ -3180,14 +3180,153 @@ void request_stepIn(const llvm::json::Object &request) {
llvm::json::Object response;
FillResponse(request, response);
auto arguments = request.getObject("arguments");
+
+ std::string step_in_target;
+ uint64_t target_id = GetUnsigned(arguments, "targetId", 0);
+ auto it = g_dap.step_in_targets.find(target_id);
+ if (it != g_dap.step_in_targets.end())
+ step_in_target = it->second;
+
+ const bool single_thread = GetBoolean(arguments, "singleThread", false);
+ lldb::RunMode run_mode =
+ single_thread ? lldb::eOnlyThisThread : lldb::eOnlyDuringStepping;
lldb::SBThread thread = g_dap.GetLLDBThread(*arguments);
if (thread.IsValid()) {
// Remember the thread ID that caused the resume so we can set the
// "threadCausedFocus" boolean value in the "stopped" events.
g_dap.focus_tid = thread.GetThreadID();
- thread.StepInto();
+ thread.StepInto(step_in_target.c_str(), run_mode);
+ } else {
+ response["success"] = llvm::json::Value(false);
+ }
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+// "StepInTargetsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "This request retrieves the possible step-in targets for
+// the specified stack frame.\nThese targets can be used in the `stepIn`
+// request.\nClients should only call this request if the corresponding
+// capability `supportsStepInTargetsRequest` is true.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "stepInTargets" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/StepInTargetsArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "StepInTargetsArguments": {
+// "type": "object",
+// "description": "Arguments for `stepInTargets` request.",
+// "properties": {
+// "frameId": {
+// "type": "integer",
+// "description": "The stack frame for which to retrieve the possible
+// step-in targets."
+// }
+// },
+// "required": [ "frameId" ]
+// },
+// "StepInTargetsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to `stepInTargets` request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "targets": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/StepInTarget"
+// },
+// "description": "The possible step-in targets of the specified
+// source location."
+// }
+// },
+// "required": [ "targets" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+void request_stepInTargets(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+
+ g_dap.step_in_targets.clear();
+ lldb::SBFrame frame = g_dap.GetLLDBFrame(*arguments);
+ if (frame.IsValid()) {
+ lldb::SBAddress pc_addr = frame.GetPCAddress();
+ lldb::SBAddress line_end_addr =
+ pc_addr.GetLineEntry().GetSameLineContiguousAddressRangeEnd(true);
+ lldb::SBInstructionList insts = g_dap.target.ReadInstructions(
+ pc_addr, line_end_addr, /*flavor_string=*/nullptr);
+
+ if (!insts.IsValid()) {
+ response["success"] = false;
+ response["message"] = "Failed to get instructions for frame.";
+ g_dap.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+
+ llvm::json::Array step_in_targets;
+ const auto num_insts = insts.GetSize();
+ for (size_t i = 0; i < num_insts; ++i) {
+ lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
+ if (!inst.IsValid())
+ break;
+
+ lldb::addr_t inst_addr = inst.GetAddress().GetLoadAddress(g_dap.target);
+
+ // Note: currently only x86/x64 supports flow kind.
+ lldb::InstructionControlFlowKind flow_kind =
+ inst.GetControlFlowKind(g_dap.target);
+ if (flow_kind == lldb::eInstructionControlFlowKindCall) {
+ // Use call site instruction address as id which is easy to debug.
+ llvm::json::Object step_in_target;
+ step_in_target["id"] = inst_addr;
+
+ llvm::StringRef call_operand_name = inst.GetOperands(g_dap.target);
+ lldb::addr_t call_target_addr;
+ if (call_operand_name.getAsInteger(0, call_target_addr))
+ continue;
----------------
jeffreytan81 wrote:
I have looked into using the comment. But it is not very portable:
```
0x55555555a426 <+934>: callq 0x555555558990 ; bar at main.cpp:64
0x55555555a42b <+939>: movl %eax, -0xb0(%rbp)
0x55555555a431 <+945>: callq 0x5555555589a0 ; bar2 at main.cpp:68
0x55555555a436 <+950>: movl -0xb0(%rbp), %edi
0x55555555a43c <+956>: movl %eax, %esi
0x55555555a43e <+958>: callq 0x555555558970 ; foo at main.cpp:60
```
1. We will have to manually parse the comment to get the target function name.
2. The function name does not include the function overloaded parameters like "foo" vs "for(int, int)".
https://github.com/llvm/llvm-project/pull/86623
More information about the lldb-commits
mailing list