-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb-dap] Migrate disassemble request to structured handler #140482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,113 +9,34 @@ | |||||
| #include "DAP.h" | ||||||
| #include "EventHelper.h" | ||||||
| #include "JSONUtils.h" | ||||||
| #include "Protocol/ProtocolRequests.h" | ||||||
| #include "Protocol/ProtocolTypes.h" | ||||||
| #include "RequestHandler.h" | ||||||
| #include "lldb/API/SBInstruction.h" | ||||||
| #include "llvm/ADT/StringExtras.h" | ||||||
|
|
||||||
| using namespace lldb_dap::protocol; | ||||||
|
|
||||||
| namespace lldb_dap { | ||||||
|
|
||||||
| // "DisassembleRequest": { | ||||||
| // "allOf": [ { "$ref": "#/definitions/Request" }, { | ||||||
| // "type": "object", | ||||||
| // "description": "Disassembles code stored at the provided | ||||||
| // location.\nClients should only call this request if the corresponding | ||||||
| // capability `supportsDisassembleRequest` is true.", "properties": { | ||||||
| // "command": { | ||||||
| // "type": "string", | ||||||
| // "enum": [ "disassemble" ] | ||||||
| // }, | ||||||
| // "arguments": { | ||||||
| // "$ref": "#/definitions/DisassembleArguments" | ||||||
| // } | ||||||
| // }, | ||||||
| // "required": [ "command", "arguments" ] | ||||||
| // }] | ||||||
| // }, | ||||||
| // "DisassembleArguments": { | ||||||
| // "type": "object", | ||||||
| // "description": "Arguments for `disassemble` request.", | ||||||
| // "properties": { | ||||||
| // "memoryReference": { | ||||||
| // "type": "string", | ||||||
| // "description": "Memory reference to the base location containing the | ||||||
| // instructions to disassemble." | ||||||
| // }, | ||||||
| // "offset": { | ||||||
| // "type": "integer", | ||||||
| // "description": "Offset (in bytes) to be applied to the reference | ||||||
| // location before disassembling. Can be negative." | ||||||
| // }, | ||||||
| // "instructionOffset": { | ||||||
| // "type": "integer", | ||||||
| // "description": "Offset (in instructions) to be applied after the byte | ||||||
| // offset (if any) before disassembling. Can be negative." | ||||||
| // }, | ||||||
| // "instructionCount": { | ||||||
| // "type": "integer", | ||||||
| // "description": "Number of instructions to disassemble starting at the | ||||||
| // specified location and offset.\nAn adapter must return exactly this | ||||||
| // number of instructions - any unavailable instructions should be | ||||||
| // replaced with an implementation-defined 'invalid instruction' value." | ||||||
| // }, | ||||||
| // "resolveSymbols": { | ||||||
| // "type": "boolean", | ||||||
| // "description": "If true, the adapter should attempt to resolve memory | ||||||
| // addresses and other values to symbolic names." | ||||||
| // } | ||||||
| // }, | ||||||
| // "required": [ "memoryReference", "instructionCount" ] | ||||||
| // }, | ||||||
| // "DisassembleResponse": { | ||||||
| // "allOf": [ { "$ref": "#/definitions/Response" }, { | ||||||
| // "type": "object", | ||||||
| // "description": "Response to `disassemble` request.", | ||||||
| // "properties": { | ||||||
| // "body": { | ||||||
| // "type": "object", | ||||||
| // "properties": { | ||||||
| // "instructions": { | ||||||
| // "type": "array", | ||||||
| // "items": { | ||||||
| // "$ref": "#/definitions/DisassembledInstruction" | ||||||
| // }, | ||||||
| // "description": "The list of disassembled instructions." | ||||||
| // } | ||||||
| // }, | ||||||
| // "required": [ "instructions" ] | ||||||
| // } | ||||||
| // } | ||||||
| // }] | ||||||
| // } | ||||||
| void DisassembleRequestHandler::operator()( | ||||||
| const llvm::json::Object &request) const { | ||||||
| llvm::json::Object response; | ||||||
| FillResponse(request, response); | ||||||
| auto *arguments = request.getObject("arguments"); | ||||||
|
|
||||||
| llvm::StringRef memoryReference = | ||||||
| GetString(arguments, "memoryReference").value_or(""); | ||||||
| auto addr_opt = DecodeMemoryReference(memoryReference); | ||||||
| if (!addr_opt.has_value()) { | ||||||
| response["success"] = false; | ||||||
| response["message"] = | ||||||
| "Malformed memory reference: " + memoryReference.str(); | ||||||
| dap.SendJSON(llvm::json::Value(std::move(response))); | ||||||
| return; | ||||||
| } | ||||||
| lldb::addr_t addr_ptr = *addr_opt; | ||||||
| /// Disassembles code stored at the provided location. | ||||||
| /// Clients should only call this request if the corresponding capability | ||||||
| /// `supportsDisassembleRequest` is true. | ||||||
| llvm::Expected<DisassembleResponseBody> | ||||||
| DisassembleRequestHandler::Run(const DisassembleArguments &args) const { | ||||||
| std::vector<DisassembledInstruction> instructions; | ||||||
|
|
||||||
| addr_ptr += GetInteger<int64_t>(arguments, "instructionOffset").value_or(0); | ||||||
| lldb::SBAddress addr(addr_ptr, dap.target); | ||||||
| if (!addr.IsValid()) { | ||||||
| response["success"] = false; | ||||||
| response["message"] = "Memory reference not found in the current binary."; | ||||||
| dap.SendJSON(llvm::json::Value(std::move(response))); | ||||||
| return; | ||||||
| } | ||||||
| auto addr_opt = DecodeMemoryReference(args.memoryReference); | ||||||
| if (!addr_opt.has_value()) | ||||||
| return llvm::make_error<DAPError>("Malformed memory reference: " + | ||||||
| args.memoryReference); | ||||||
|
|
||||||
| const auto inst_count = | ||||||
| GetInteger<int64_t>(arguments, "instructionCount").value_or(0); | ||||||
| lldb::addr_t addr_ptr = *addr_opt; | ||||||
| addr_ptr += args.instructionOffset.value_or(0); | ||||||
| lldb::SBAddress addr(addr_ptr, dap.target); | ||||||
| if (!addr.IsValid()) | ||||||
| return llvm::make_error<DAPError>( | ||||||
| "Memory reference not found in the current binary."); | ||||||
|
|
||||||
| std::string flavor_string; | ||||||
| const auto target_triple = llvm::StringRef(dap.target.GetTriple()); | ||||||
|
|
@@ -132,19 +53,14 @@ void DisassembleRequestHandler::operator()( | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| lldb::SBInstructionList insts = | ||||||
| dap.target.ReadInstructions(addr, inst_count, flavor_string.c_str()); | ||||||
| lldb::SBInstructionList insts = dap.target.ReadInstructions( | ||||||
| addr, args.instructionCount, flavor_string.c_str()); | ||||||
|
|
||||||
| if (!insts.IsValid()) { | ||||||
| response["success"] = false; | ||||||
| response["message"] = "Failed to find instructions for memory address."; | ||||||
| dap.SendJSON(llvm::json::Value(std::move(response))); | ||||||
| return; | ||||||
| } | ||||||
| if (!insts.IsValid()) | ||||||
| return llvm::make_error<DAPError>( | ||||||
| "Failed to find instructions for memory address."); | ||||||
|
|
||||||
| const bool resolveSymbols = | ||||||
| GetBoolean(arguments, "resolveSymbols").value_or(false); | ||||||
| llvm::json::Array instructions; | ||||||
| const bool resolveSymbols = args.resolveSymbols.value_or(false); | ||||||
|
||||||
| const bool resolveSymbols = args.resolveSymbols.value_or(false); | |
| const bool resolve_symbols = args.resolveSymbols.value_or(false); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -726,6 +726,41 @@ struct SetDataBreakpointsResponseBody { | |
| }; | ||
| llvm::json::Value toJSON(const SetDataBreakpointsResponseBody &); | ||
|
|
||
| /// Arguments to `disassemble` request. | ||
| struct DisassembleArguments { | ||
| /// Memory reference to the base location containing the instructions to | ||
| /// disassemble. | ||
| std::string memoryReference; | ||
|
|
||
| /// Offset (in bytes) to be applied to the reference location before | ||
| /// disassembling. Can be negative. | ||
| std::optional<int64_t> offset; | ||
|
|
||
| /// Offset (in instructions) to be applied after the byte offset (if any) | ||
| /// before disassembling. Can be negative. | ||
| std::optional<int64_t> instructionOffset; | ||
|
|
||
| /// Number of instructions to disassemble starting at the specified location | ||
| /// and offset. | ||
| /// An adapter must return exactly this number of instructions - any | ||
| /// unavailable instructions should be replaced with an implementation-defined | ||
| /// 'invalid instruction' value. | ||
| uint32_t instructionCount; | ||
|
|
||
| /// If true, the adapter should attempt to resolve memory addresses and other | ||
| /// values to symbolic names. | ||
| std::optional<bool> resolveSymbols; | ||
| }; | ||
| bool fromJSON(const llvm::json::Value &, DisassembleArguments &, | ||
| llvm::json::Path); | ||
|
Comment on lines
+754
to
+755
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add the toJSON forward declaration. |
||
|
|
||
| /// Response to `disassemble` request. | ||
| struct DisassembleResponseBody { | ||
| /// The list of disassembled instructions. | ||
| std::vector<DisassembledInstruction> instructions; | ||
| }; | ||
| llvm::json::Value toJSON(const DisassembleResponseBody &); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add the fromJSON forward declaration. |
||
|
|
||
| } // namespace lldb_dap::protocol | ||
|
|
||
| #endif | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is existing code, but since you're touching it, let's use the actual type here. (auto in llvm)