================
@@ -56,100 +54,204 @@ DisassembleRequestHandler::Run(const DisassembleArguments 
&args) const {
     }
   }
 
+  int64_t instructionOffset = args.instructionOffset.value_or(0);
+  if (instructionOffset > 0) {
+    lldb::SBInstructionList forward_insts = dap.target.ReadInstructions(
+        addr, instructionOffset + 1, flavor_string.c_str());
+    if (forward_insts.GetSize() != static_cast<size_t>(instructionOffset + 1)) 
{
+      return llvm::make_error<DAPError>(
+          "Failed to disassemble instructions after " +
+          std::to_string(instructionOffset) +
+          " instructions from the given address.");
+    }
+
+    addr = forward_insts.GetInstructionAtIndex(instructionOffset).GetAddress();
+  }
+
+  const bool resolve_symbols = args.resolveSymbols.value_or(false);
+  std::vector<DisassembledInstruction> instructions;
+  if (instructionOffset < 0)
+    instructions = disassembleBackwards(addr, std::abs(instructionOffset),
+                                        flavor_string.c_str(), 
resolve_symbols);
+
+  const auto instructions_left = args.instructionCount - instructions.size();
   lldb::SBInstructionList insts = dap.target.ReadInstructions(
-      addr, args.instructionCount, flavor_string.c_str());
+      addr, instructions_left, flavor_string.c_str());
 
   if (!insts.IsValid())
     return llvm::make_error<DAPError>(
         "Failed to find instructions for memory address.");
 
-  const bool resolve_symbols = args.resolveSymbols.value_or(false);
+  // add the disassembly from the given address forward
   const auto num_insts = insts.GetSize();
-  for (size_t i = 0; i < num_insts; ++i) {
+  for (size_t i = 0;
+       i < num_insts && instructions.size() < args.instructionCount; ++i) {
     lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
-    auto addr = inst.GetAddress();
-    const auto inst_addr = addr.GetLoadAddress(dap.target);
-    const char *m = inst.GetMnemonic(dap.target);
-    const char *o = inst.GetOperands(dap.target);
-    const char *c = inst.GetComment(dap.target);
-    auto d = inst.GetData(dap.target);
-
-    std::string bytes;
-    llvm::raw_string_ostream sb(bytes);
-    for (unsigned i = 0; i < inst.GetByteSize(); i++) {
-      lldb::SBError error;
-      uint8_t b = d.GetUnsignedInt8(error, i);
-      if (error.Success()) {
-        sb << llvm::format("%2.2x ", b);
-      }
-    }
+    instructions.push_back(
+        SBInstructionToDisassembledInstruction(inst, resolve_symbols));
+  }
 
-    DisassembledInstruction disassembled_inst;
-    disassembled_inst.address = inst_addr;
-    disassembled_inst.instructionBytes =
-        bytes.size() > 0 ? bytes.substr(0, bytes.size() - 1) : "";
-
-    std::string instruction;
-    llvm::raw_string_ostream si(instruction);
-
-    lldb::SBSymbol symbol = addr.GetSymbol();
-    // Only add the symbol on the first line of the function.
-    if (symbol.IsValid() && symbol.GetStartAddress() == addr) {
-      // If we have a valid symbol, append it as a label prefix for the first
-      // instruction. This is so you can see the start of a function/callsite
-      // in the assembly, at the moment VS Code (1.80) does not visualize the
-      // symbol associated with the assembly instruction.
-      si << (symbol.GetMangledName() != nullptr ? symbol.GetMangledName()
-                                                : symbol.GetName())
-         << ": ";
-
-      if (resolve_symbols)
-        disassembled_inst.symbol = symbol.GetDisplayName();
-    }
+  // Pad the instructions with invalid instructions if needed.
+  if (instructions.size() < args.instructionCount)
+    for (size_t i = instructions.size(); i < args.instructionCount; ++i)
+      instructions.push_back(GetInvalidInstruction());
 
-    si << llvm::formatv("{0,7} {1,12}", m, o);
-    if (c && c[0]) {
-      si << " ; " << c;
-    }
+  return DisassembleResponseBody{std::move(instructions)};
+}
+
+std::vector<protocol::DisassembledInstruction>
+DisassembleRequestHandler::disassembleBackwards(
+    lldb::SBAddress &addr, const uint32_t instruction_count,
+    const char *flavor_string, bool resolve_symbols) const {
+  std::vector<DisassembledInstruction> instructions;
 
-    disassembled_inst.instruction = instruction;
-
-    auto line_entry = addr.GetLineEntry();
-    // If the line number is 0 then the entry represents a compiler generated
-    // location.
-    if (line_entry.GetStartAddress() == addr && line_entry.IsValid() &&
-        line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) {
-      auto source = CreateSource(line_entry);
-      disassembled_inst.location = std::move(source);
-
-      const auto line = line_entry.GetLine();
-      if (line != 0 && line != LLDB_INVALID_LINE_NUMBER)
-        disassembled_inst.line = line;
-
-      const auto column = line_entry.GetColumn();
-      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 != 0 && end_line != LLDB_INVALID_LINE_NUMBER &&
-            end_line != line) {
-          disassembled_inst.endLine = end_line;
-
-          const auto end_column = end_line_entry.GetColumn();
-          if (end_column != 0 && end_column != LLDB_INVALID_COLUMN_NUMBER &&
-              end_column != column)
-            disassembled_inst.endColumn = end_column - 1;
+  if (dap.target.GetMinimumOpcodeByteSize() ==
+      dap.target.GetMaximumOpcodeByteSize()) {
+    // If the target has a fixed opcode size, we can disassemble backwards
+    // directly.
+    lldb::addr_t disassemble_start_load_addr =
+        addr.GetLoadAddress(dap.target) -
+        (instruction_count * dap.target.GetMinimumOpcodeByteSize());
+    lldb::SBAddress disassemble_start_addr(disassemble_start_load_addr,
+                                           dap.target);
+    lldb::SBInstructionList backwards_insts =
+        dap.target.ReadInstructions(addr, instruction_count, flavor_string);
+    if (backwards_insts.IsValid()) {
+      for (size_t i = 0; i < backwards_insts.GetSize(); ++i) {
+        lldb::SBInstruction inst = backwards_insts.GetInstructionAtIndex(i);
+        instructions.push_back(
+            SBInstructionToDisassembledInstruction(inst, resolve_symbols));
+      }
+      return instructions;
+    }
+  } else {
+    // There is no opcode fixed size so we have no idea where are the valid
+    // instructions before the current address. let's try from the start of the
+    // symbol if available.
+    auto symbol = addr.GetSymbol();
+    if (symbol.IsValid()) {
+      // add valid instructions before the current instruction using the 
symbol.
+      lldb::SBInstructionList symbol_insts = dap.target.ReadInstructions(
+          symbol.GetStartAddress(), addr, flavor_string);
+      if (symbol_insts.IsValid()) {
+        size_t backwards_insts_start =
+            symbol_insts.GetSize() >= instruction_count
+                ? symbol_insts.GetSize() - instruction_count
+                : 0;
+        for (size_t i = backwards_insts_start;
+             i < symbol_insts.GetSize() &&
+             instructions.size() < instruction_count;
+             ++i) {
+          lldb::SBInstruction inst = symbol_insts.GetInstructionAtIndex(i);
+          instructions.push_back(
+              SBInstructionToDisassembledInstruction(inst, resolve_symbols));
         }
       }
     }
+  }
 
-    instructions.push_back(std::move(disassembled_inst));
+  // pad the instructions with invalid instructions if needed.
+  while (instructions.size() < instruction_count) {
+    instructions.insert(instructions.begin(), GetInvalidInstruction());
----------------
JDevlieghere wrote:

So we're only padding when we don't have a fixed opcode size because of the 
early return on line 125 (unless the instruction isn't valid).  
```suggestion
  // Pad the instructions with invalid instructions if needed.
  while (instructions.size() < instruction_count) 
    instructions.insert(instructions.begin(), GetInvalidInstruction());
```

https://github.com/llvm/llvm-project/pull/140486
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to