https://github.com/eronnen updated 
https://github.com/llvm/llvm-project/pull/140482

>From 1014235896b79eb4ea05a6822714a66adaa691ac Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Sun, 18 May 2025 23:51:58 +0200
Subject: [PATCH 1/4] [lldb-dap] Migrate disassemble request to structured
 handler

---
 .../Handler/DisassembleRequestHandler.cpp     | 183 +++++-------------
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |   9 +-
 .../lldb-dap/Protocol/ProtocolRequests.cpp    |  18 ++
 .../lldb-dap/Protocol/ProtocolRequests.h      |  35 ++++
 .../tools/lldb-dap/Protocol/ProtocolTypes.cpp |  34 ++++
 lldb/tools/lldb-dap/Protocol/ProtocolTypes.h  |  54 ++++++
 6 files changed, 193 insertions(+), 140 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
index d738f54ff1a9f..938078947259b 100644
--- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
@@ -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 auto num_insts = insts.GetSize();
   for (size_t i = 0; i < num_insts; ++i) {
     lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
@@ -165,11 +81,10 @@ void DisassembleRequestHandler::operator()(
       }
     }
 
-    llvm::json::Object disassembled_inst{
-        {"address", "0x" + llvm::utohexstr(inst_addr)},
-        {"instructionBytes",
-         bytes.size() > 0 ? bytes.substr(0, bytes.size() - 1) : ""},
-    };
+    DisassembledInstruction disassembled_inst;
+    disassembled_inst.address = "0x" + llvm::utohexstr(inst_addr);
+    disassembled_inst.instructionBytes =
+        bytes.size() > 0 ? bytes.substr(0, bytes.size() - 1) : "";
 
     std::string instruction;
     llvm::raw_string_ostream si(instruction);
@@ -185,9 +100,8 @@ void DisassembleRequestHandler::operator()(
                                                 : symbol.GetName())
          << ": ";
 
-      if (resolveSymbols) {
-        disassembled_inst.try_emplace("symbol", symbol.GetDisplayName());
-      }
+      if (resolveSymbols)
+        disassembled_inst.symbol = symbol.GetDisplayName();
     }
 
     si << llvm::formatv("{0,7} {1,12}", m, o);
@@ -195,7 +109,7 @@ void DisassembleRequestHandler::operator()(
       si << " ; " << c;
     }
 
-    disassembled_inst.try_emplace("instruction", instruction);
+    disassembled_inst.instruction = instruction;
 
     auto line_entry = addr.GetLineEntry();
     // If the line number is 0 then the entry represents a compiler generated
@@ -203,41 +117,36 @@ void DisassembleRequestHandler::operator()(
     if (line_entry.GetStartAddress() == addr && line_entry.IsValid() &&
         line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) {
       auto source = CreateSource(line_entry);
-      disassembled_inst.try_emplace("location", source);
+      disassembled_inst.location = std::move(source);
 
       const auto line = line_entry.GetLine();
-      if (line && line != LLDB_INVALID_LINE_NUMBER) {
-        disassembled_inst.try_emplace("line", line);
-      }
+      if (line != 0 && line != LLDB_INVALID_LINE_NUMBER)
+        disassembled_inst.line = line;
+
       const auto column = line_entry.GetColumn();
-      if (column && column != LLDB_INVALID_COLUMN_NUMBER) {
-        disassembled_inst.try_emplace("column", column);
-      }
+      if (column != 0 && column != LLDB_INVALID_COLUMN_NUMBER)
+        disassembled_inst.column = column;
 
       auto end_line_entry = line_entry.GetEndAddress().GetLineEntry();
       if (end_line_entry.IsValid() &&
           end_line_entry.GetFileSpec() == line_entry.GetFileSpec()) {
         const auto end_line = end_line_entry.GetLine();
-        if (end_line && end_line != LLDB_INVALID_LINE_NUMBER &&
+        if (end_line != 0 && end_line != LLDB_INVALID_LINE_NUMBER &&
             end_line != line) {
-          disassembled_inst.try_emplace("endLine", end_line);
+          disassembled_inst.endLine = end_line;
 
           const auto end_column = end_line_entry.GetColumn();
-          if (end_column && end_column != LLDB_INVALID_COLUMN_NUMBER &&
-              end_column != column) {
-            disassembled_inst.try_emplace("endColumn", end_column - 1);
-          }
+          if (end_column != 0 && end_column != LLDB_INVALID_COLUMN_NUMBER &&
+              end_column != column)
+            disassembled_inst.endColumn = end_column - 1;
         }
       }
     }
 
-    instructions.emplace_back(std::move(disassembled_inst));
+    instructions.push_back(std::move(disassembled_inst));
   }
 
-  llvm::json::Object body;
-  body.try_emplace("instructions", std::move(instructions));
-  response.try_emplace("body", std::move(body));
-  dap.SendJSON(llvm::json::Value(std::move(response)));
+  return DisassembleResponseBody{std::move(instructions)};
 }
 
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index e6bccfe12f402..998b98137a1ea 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -534,14 +534,17 @@ class LocationsRequestHandler : public 
LegacyRequestHandler {
   void operator()(const llvm::json::Object &request) const override;
 };
 
-class DisassembleRequestHandler : public LegacyRequestHandler {
+class DisassembleRequestHandler final
+    : public RequestHandler<protocol::DisassembleArguments,
+                            llvm::Expected<protocol::DisassembleResponseBody>> 
{
 public:
-  using LegacyRequestHandler::LegacyRequestHandler;
+  using RequestHandler::RequestHandler;
   static llvm::StringLiteral GetCommand() { return "disassemble"; }
   FeatureSet GetSupportedFeatures() const override {
     return {protocol::eAdapterFeatureDisassembleRequest};
   }
-  void operator()(const llvm::json::Object &request) const override;
+  llvm::Expected<protocol::DisassembleResponseBody>
+  Run(const protocol::DisassembleArguments &args) const override;
 };
 
 class ReadMemoryRequestHandler : public LegacyRequestHandler {
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index 7efab87d39986..4160077d419e1 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -460,4 +460,22 @@ llvm::json::Value toJSON(const 
SetDataBreakpointsResponseBody &SDBR) {
   return result;
 }
 
+bool fromJSON(const llvm::json::Value &Params, DisassembleArguments &DA,
+              llvm::json::Path P) {
+  json::ObjectMapper O(Params, P);
+  return O && O.map("memoryReference", DA.memoryReference) &&
+         O.mapOptional("offset", DA.offset) &&
+         O.mapOptional("instructionOffset", DA.instructionOffset) &&
+         O.map("instructionCount", DA.instructionCount) &&
+         O.mapOptional("resolveSymbols", DA.resolveSymbols);
+}
+
+llvm::json::Value toJSON(const DisassembleResponseBody &DRB) {
+  llvm::json::Array instructions;
+  for (const auto &instruction : DRB.instructions) {
+    instructions.push_back(toJSON(instruction));
+  }
+  return llvm::json::Object{{"instructions", std::move(instructions)}};
+}
+
 } // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index b421c631344de..c41f3a7296563 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -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);
+
+/// Response to `disassemble` request.
+struct DisassembleResponseBody {
+  /// The list of disassembled instructions.
+  std::vector<DisassembledInstruction> instructions;
+};
+llvm::json::Value toJSON(const DisassembleResponseBody &);
+
 } // namespace lldb_dap::protocol
 
 #endif
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index ce7519e3b16b8..94fe236d952a7 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -782,4 +782,38 @@ bool fromJSON(const llvm::json::Value &Params, 
InstructionBreakpoint &IB,
          O.mapOptional("mode", IB.mode);
 }
 
+llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &PH) {
+  switch (PH) {
+  case DisassembledInstruction::eSourcePresentationHintNormal:
+    return "normal";
+  case DisassembledInstruction::eSourcePresentationHintInvalid:
+    return "invalid";
+  }
+  llvm_unreachable("unhandled presentation hint.");
+}
+
+llvm::json::Value toJSON(const DisassembledInstruction &DI) {
+  llvm::json::Object result{{"address", DI.address},
+                            {"instruction", DI.instruction}};
+
+  if (DI.instructionBytes)
+    result.insert({"instructionBytes", *DI.instructionBytes});
+  if (DI.symbol)
+    result.insert({"symbol", *DI.symbol});
+  if (DI.location)
+    result.insert({"location", *DI.location});
+  if (DI.line)
+    result.insert({"line", *DI.line});
+  if (DI.column)
+    result.insert({"column", *DI.column});
+  if (DI.endLine)
+    result.insert({"endLine", *DI.endLine});
+  if (DI.endColumn)
+    result.insert({"endColumn", *DI.endColumn});
+  if (DI.presentationHint)
+    result.insert({"presentationHint", *DI.presentationHint});
+
+  return result;
+}
+
 } // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 3df77ee7374a7..5c6858904a3cf 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -627,6 +627,60 @@ struct InstructionBreakpoint {
 bool fromJSON(const llvm::json::Value &, InstructionBreakpoint &,
               llvm::json::Path);
 
+/// Properties of a single disassembled instruction, returned by `disassemble`
+/// request.
+struct DisassembledInstruction {
+  enum PresentationHint : unsigned {
+    eSourcePresentationHintNormal,
+    eSourcePresentationHintInvalid,
+  };
+
+  /// The address of the instruction. Treated as a hex value if prefixed with
+  /// `0x`, or as a decimal value otherwise.
+  std::string address;
+
+  /// Raw bytes representing the instruction and its operands, in an
+  /// implementation-defined format.
+  std::optional<std::string> instructionBytes;
+
+  /// Text representing the instruction and its operands, in an
+  /// implementation-defined format.
+  std::string instruction;
+
+  /// Name of the symbol that corresponds with the location of this 
instruction,
+  /// if any.
+  std::optional<std::string> symbol;
+
+  /// Source location that corresponds to this instruction, if any.
+  /// Should always be set (if available) on the first instruction returned,
+  /// but can be omitted afterwards if this instruction maps to the same source
+  /// file as the previous instruction.
+  std::optional<protocol::Source> location;
+
+  /// The line within the source location that corresponds to this instruction,
+  /// if any.
+  std::optional<uint32_t> line;
+
+  /// The column within the line that corresponds to this instruction, if any.
+  std::optional<uint32_t> column;
+
+  /// The end line of the range that corresponds to this instruction, if any.
+  std::optional<uint32_t> endLine;
+
+  /// The end column of the range that corresponds to this instruction, if any.
+  std::optional<uint32_t> endColumn;
+
+  /// A hint for how to present the instruction in the UI.
+  ///
+  /// A value of `invalid` may be used to indicate this instruction is 'filler'
+  /// and cannot be reached by the program. For example, unreadable memory
+  /// addresses may be presented is 'invalid.'
+  /// Values: 'normal', 'invalid'
+  std::optional<PresentationHint> presentationHint;
+};
+llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &);
+llvm::json::Value toJSON(const DisassembledInstruction &);
+
 } // namespace lldb_dap::protocol
 
 #endif

>From 304c28f47a05e0753125bd85b343fd17e0994afd Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Mon, 19 May 2025 10:16:29 +0200
Subject: [PATCH 2/4] adding DisassembledInstruction unit tests

---
 .../Handler/DisassembleRequestHandler.cpp     |  2 +-
 .../tools/lldb-dap/Protocol/ProtocolTypes.cpp | 60 +++++++++++++++-
 lldb/tools/lldb-dap/Protocol/ProtocolTypes.h  | 10 ++-
 lldb/unittests/DAP/ProtocolTypesTest.cpp      | 72 +++++++++++++++++++
 4 files changed, 137 insertions(+), 7 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
index 938078947259b..60165a357e735 100644
--- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
@@ -82,7 +82,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments 
&args) const {
     }
 
     DisassembledInstruction disassembled_inst;
-    disassembled_inst.address = "0x" + llvm::utohexstr(inst_addr);
+    disassembled_inst.address = inst_addr;
     disassembled_inst.instructionBytes =
         bytes.size() > 0 ? bytes.substr(0, bytes.size() - 1) : "";
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 94fe236d952a7..52c11ad828993 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -7,6 +7,9 @@
 
//===----------------------------------------------------------------------===//
 
 #include "Protocol/ProtocolTypes.h"
+#include "JSONUtils.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/JSON.h"
@@ -782,18 +785,69 @@ bool fromJSON(const llvm::json::Value &Params, 
InstructionBreakpoint &IB,
          O.mapOptional("mode", IB.mode);
 }
 
+bool fromJSON(const llvm::json::Value &Params,
+              DisassembledInstruction::PresentationHint &PH,
+              llvm::json::Path P) {
+  auto rawHint = Params.getAsString();
+  if (!rawHint) {
+    P.report("expected a string");
+    return false;
+  }
+  std::optional<DisassembledInstruction::PresentationHint> hint =
+      StringSwitch<std::optional<DisassembledInstruction::PresentationHint>>(
+          *rawHint)
+          .Case("normal", DisassembledInstruction::
+                              eDisassembledInstructionPresentationHintNormal)
+          .Case("invalid", DisassembledInstruction::
+                               eDisassembledInstructionPresentationHintInvalid)
+          .Default(std::nullopt);
+  if (!hint) {
+    P.report("unexpected value");
+    return false;
+  }
+  PH = *hint;
+  return true;
+}
+
 llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &PH) {
   switch (PH) {
-  case DisassembledInstruction::eSourcePresentationHintNormal:
+  case DisassembledInstruction::eDisassembledInstructionPresentationHintNormal:
     return "normal";
-  case DisassembledInstruction::eSourcePresentationHintInvalid:
+  case 
DisassembledInstruction::eDisassembledInstructionPresentationHintInvalid:
     return "invalid";
   }
   llvm_unreachable("unhandled presentation hint.");
 }
 
+bool fromJSON(const llvm::json::Value &Params, DisassembledInstruction &DI,
+              llvm::json::Path P) {
+  std::optional<llvm::StringRef> raw_address =
+      Params.getAsObject()->getString("address");
+  if (!raw_address) {
+    P.report("missing `address` field");
+    return false;
+  }
+
+  std::optional<lldb::addr_t> address = DecodeMemoryReference(*raw_address);
+  if (!address) {
+    P.report("invalid `address`");
+    return false;
+  }
+
+  DI.address = *address;
+  llvm::json::ObjectMapper O(Params, P);
+  return O && O.map("instruction", DI.instruction) &&
+         O.mapOptional("instructionBytes", DI.instructionBytes) &&
+         O.mapOptional("symbol", DI.symbol) &&
+         O.mapOptional("location", DI.location) &&
+         O.mapOptional("line", DI.line) && O.mapOptional("column", DI.column) 
&&
+         O.mapOptional("endLine", DI.endLine) &&
+         O.mapOptional("endColumn", DI.endColumn) &&
+         O.mapOptional("presentationHint", DI.presentationHint);
+}
+
 llvm::json::Value toJSON(const DisassembledInstruction &DI) {
-  llvm::json::Object result{{"address", DI.address},
+  llvm::json::Object result{{"address", "0x" + llvm::utohexstr(DI.address)},
                             {"instruction", DI.instruction}};
 
   if (DI.instructionBytes)
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 5c6858904a3cf..5bac62adcdd38 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -631,13 +631,13 @@ bool fromJSON(const llvm::json::Value &, 
InstructionBreakpoint &,
 /// request.
 struct DisassembledInstruction {
   enum PresentationHint : unsigned {
-    eSourcePresentationHintNormal,
-    eSourcePresentationHintInvalid,
+    eDisassembledInstructionPresentationHintNormal,
+    eDisassembledInstructionPresentationHintInvalid,
   };
 
   /// The address of the instruction. Treated as a hex value if prefixed with
   /// `0x`, or as a decimal value otherwise.
-  std::string address;
+  lldb::addr_t address;
 
   /// Raw bytes representing the instruction and its operands, in an
   /// implementation-defined format.
@@ -678,7 +678,11 @@ struct DisassembledInstruction {
   /// Values: 'normal', 'invalid'
   std::optional<PresentationHint> presentationHint;
 };
+bool fromJSON(const llvm::json::Value &,
+              DisassembledInstruction::PresentationHint &, llvm::json::Path);
 llvm::json::Value toJSON(const DisassembledInstruction::PresentationHint &);
+bool fromJSON(const llvm::json::Value &, DisassembledInstruction &,
+              llvm::json::Path);
 llvm::json::Value toJSON(const DisassembledInstruction &);
 
 } // namespace lldb_dap::protocol
diff --git a/lldb/unittests/DAP/ProtocolTypesTest.cpp 
b/lldb/unittests/DAP/ProtocolTypesTest.cpp
index 5d5125dc78fba..41703f4a071fb 100644
--- a/lldb/unittests/DAP/ProtocolTypesTest.cpp
+++ b/lldb/unittests/DAP/ProtocolTypesTest.cpp
@@ -530,3 +530,75 @@ TEST(ProtocolTypesTest, ChecksumAlgorithm) {
   llvm::json::Path::Root root;
   EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
 }
+
+TEST(ProtocolTypesTest, DisassembledInstructionPresentationHint) {
+  // Test all PresentationHint values.
+  std::vector<
+      std::pair<DisassembledInstruction::PresentationHint, llvm::StringRef>>
+      test_cases = {{DisassembledInstruction::
+                         eDisassembledInstructionPresentationHintNormal,
+                     "normal"},
+                    {DisassembledInstruction::
+                         eDisassembledInstructionPresentationHintInvalid,
+                     "invalid"}};
+
+  for (const auto &test_case : test_cases) {
+    // Serialize the PresentationHint to JSON.
+    llvm::json::Value serialized = toJSON(test_case.first);
+    ASSERT_EQ(serialized.kind(), llvm::json::Value::Kind::String);
+    EXPECT_EQ(serialized.getAsString(), test_case.second);
+
+    // Deserialize the JSON back to PresentationHint.
+    DisassembledInstruction::PresentationHint deserialized;
+    llvm::json::Path::Root root;
+    ASSERT_TRUE(fromJSON(serialized, deserialized, root))
+        << llvm::toString(root.getError());
+    EXPECT_EQ(deserialized, test_case.first);
+  }
+
+  // Test invalid value.
+  llvm::json::Value invalid_value = "invalid_hint";
+  DisassembledInstruction::PresentationHint deserialized_invalid;
+  llvm::json::Path::Root root;
+  EXPECT_FALSE(fromJSON(invalid_value, deserialized_invalid, root));
+}
+
+TEST(ProtocolTypesTest, DisassembledInstruction) {
+  DisassembledInstruction instruction;
+  instruction.address = 0x12345678;
+  instruction.instructionBytes = "0F 1F 00";
+  instruction.instruction = "mov eax, ebx";
+  instruction.symbol = "main";
+  instruction.location = Source{"test.cpp", "/path/to/test.cpp", 123,
+                                Source::eSourcePresentationHintNormal};
+  instruction.line = 10;
+  instruction.column = 5;
+  instruction.endLine = 15;
+  instruction.endColumn = 10;
+  instruction.presentationHint =
+      DisassembledInstruction::eDisassembledInstructionPresentationHintNormal;
+
+  llvm::Expected<DisassembledInstruction> deserialized_instruction =
+      roundtrip(instruction);
+  ASSERT_THAT_EXPECTED(deserialized_instruction, llvm::Succeeded());
+
+  EXPECT_EQ(instruction.address, deserialized_instruction->address);
+  EXPECT_EQ(instruction.instructionBytes,
+            deserialized_instruction->instructionBytes);
+  EXPECT_EQ(instruction.instruction, deserialized_instruction->instruction);
+  EXPECT_EQ(instruction.symbol, deserialized_instruction->symbol);
+  EXPECT_EQ(instruction.location->name,
+            deserialized_instruction->location->name);
+  EXPECT_EQ(instruction.location->path,
+            deserialized_instruction->location->path);
+  EXPECT_EQ(instruction.location->sourceReference,
+            deserialized_instruction->location->sourceReference);
+  EXPECT_EQ(instruction.location->presentationHint,
+            deserialized_instruction->location->presentationHint);
+  EXPECT_EQ(instruction.line, deserialized_instruction->line);
+  EXPECT_EQ(instruction.column, deserialized_instruction->column);
+  EXPECT_EQ(instruction.endLine, deserialized_instruction->endLine);
+  EXPECT_EQ(instruction.endColumn, deserialized_instruction->endColumn);
+  EXPECT_EQ(instruction.presentationHint,
+            deserialized_instruction->presentationHint);
+}

>From 7d45343a4f7857aa2b61b4413952e902bed3971a Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Mon, 19 May 2025 10:32:02 +0200
Subject: [PATCH 3/4] remove auto

---
 lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
index 60165a357e735..e65d46859ad5a 100644
--- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
@@ -13,7 +13,9 @@
 #include "Protocol/ProtocolTypes.h"
 #include "RequestHandler.h"
 #include "lldb/API/SBInstruction.h"
+#include "lldb/lldb-types.h"
 #include "llvm/ADT/StringExtras.h"
+#include <optional>
 
 using namespace lldb_dap::protocol;
 
@@ -26,7 +28,8 @@ llvm::Expected<DisassembleResponseBody>
 DisassembleRequestHandler::Run(const DisassembleArguments &args) const {
   std::vector<DisassembledInstruction> instructions;
 
-  auto addr_opt = DecodeMemoryReference(args.memoryReference);
+  std::optional<lldb::addr_t> addr_opt =
+      DecodeMemoryReference(args.memoryReference);
   if (!addr_opt.has_value())
     return llvm::make_error<DAPError>("Malformed memory reference: " +
                                       args.memoryReference);

>From 08c91726d60c3e38e3001b998cd7540d2b7449ed Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Mon, 19 May 2025 21:16:51 +0200
Subject: [PATCH 4/4] small CR fixes

---
 lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp | 4 ++--
 lldb/tools/lldb-dap/Protocol/ProtocolRequests.h           | 3 +++
 lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp            | 4 ++--
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
index e65d46859ad5a..d779de1e8e834 100644
--- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp
@@ -63,7 +63,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments 
&args) const {
     return llvm::make_error<DAPError>(
         "Failed to find instructions for memory address.");
 
-  const bool resolveSymbols = args.resolveSymbols.value_or(false);
+  const bool resolve_symbols = args.resolveSymbols.value_or(false);
   const auto num_insts = insts.GetSize();
   for (size_t i = 0; i < num_insts; ++i) {
     lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
@@ -103,7 +103,7 @@ DisassembleRequestHandler::Run(const DisassembleArguments 
&args) const {
                                                 : symbol.GetName())
          << ": ";
 
-      if (resolveSymbols)
+      if (resolve_symbols)
         disassembled_inst.symbol = symbol.GetDisplayName();
     }
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index c41f3a7296563..7c774e50d6e56 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -753,12 +753,15 @@ struct DisassembleArguments {
 };
 bool fromJSON(const llvm::json::Value &, DisassembleArguments &,
               llvm::json::Path);
+llvm::json::Value toJSON(const DisassembleArguments &);
 
 /// Response to `disassemble` request.
 struct DisassembleResponseBody {
   /// The list of disassembled instructions.
   std::vector<DisassembledInstruction> instructions;
 };
+bool fromJSON(const llvm::json::Value &, DisassembleResponseBody &,
+              llvm::json::Path);
 llvm::json::Value toJSON(const DisassembleResponseBody &);
 
 } // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
index 52c11ad828993..8d4fbd18fee7c 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.cpp
@@ -824,13 +824,13 @@ bool fromJSON(const llvm::json::Value &Params, 
DisassembledInstruction &DI,
   std::optional<llvm::StringRef> raw_address =
       Params.getAsObject()->getString("address");
   if (!raw_address) {
-    P.report("missing `address` field");
+    P.report("missing 'address' field");
     return false;
   }
 
   std::optional<lldb::addr_t> address = DecodeMemoryReference(*raw_address);
   if (!address) {
-    P.report("invalid `address`");
+    P.report("invalid 'address'");
     return false;
   }
 

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to