@@ -24,15 +24,14 @@ namespace lldb_dap {
2424// / `supportsDisassembleRequest` is true.
2525llvm::Expected<DisassembleResponseBody>
2626DisassembleRequestHandler::Run (const DisassembleArguments &args) const {
27- std::vector<DisassembledInstruction> instructions;
28-
2927 auto addr_opt = DecodeMemoryReference (args.memoryReference );
3028 if (!addr_opt.has_value ())
3129 return llvm::make_error<DAPError>(" Malformed memory reference: " +
3230 args.memoryReference );
3331
3432 lldb::addr_t addr_ptr = *addr_opt;
35- addr_ptr += args.instructionOffset .value_or (0 );
33+ addr_ptr += args.offset .value_or (0 );
34+
3635 lldb::SBAddress addr (addr_ptr, dap.target );
3736 if (!addr.IsValid ())
3837 return llvm::make_error<DAPError>(
@@ -53,100 +52,171 @@ DisassembleRequestHandler::Run(const DisassembleArguments &args) const {
5352 }
5453 }
5554
56- lldb::SBInstructionList insts = dap.target .ReadInstructions (
57- addr, args.instructionCount , flavor_string.c_str ());
55+ int64_t instructionOffset = args.instructionOffset .value_or (0 );
56+ if (instructionOffset > 0 ) {
57+ lldb::SBInstructionList forward_insts = dap.target .ReadInstructions (
58+ addr, instructionOffset + 1 , flavor_string.c_str ());
59+ if (forward_insts.GetSize () != static_cast <size_t >(instructionOffset + 1 )) {
60+ return llvm::make_error<DAPError>(
61+ " Failed to disassemble instructions after " +
62+ std::to_string (instructionOffset) +
63+ " instructions from the given address." );
64+ }
5865
66+ addr = forward_insts.GetInstructionAtIndex (instructionOffset).GetAddress ();
67+ }
68+
69+ const bool resolveSymbols = args.resolveSymbols .value_or (false );
70+ std::vector<DisassembledInstruction> instructions;
71+ if (instructionOffset < 0 ) {
72+ // need to disassemble backwards, let's try from the start of the symbol if
73+ // available.
74+ size_t number_of_insts_before = std::abs (instructionOffset);
75+ auto symbol = addr.GetSymbol ();
76+ if (symbol.IsValid ()) {
77+ // add valid instructions before the current instruction using the symbol.
78+ lldb::SBInstructionList symbol_insts = dap.target .ReadInstructions (
79+ symbol.GetStartAddress (), addr, flavor_string.c_str ());
80+ if (symbol_insts.IsValid ()) {
81+ size_t backwards_insts_start =
82+ symbol_insts.GetSize () >= number_of_insts_before
83+ ? symbol_insts.GetSize () - number_of_insts_before
84+ : 0 ;
85+ for (size_t i = backwards_insts_start;
86+ i < symbol_insts.GetSize () &&
87+ instructions.size () < args.instructionCount ;
88+ ++i) {
89+ lldb::SBInstruction inst = symbol_insts.GetInstructionAtIndex (i);
90+ instructions.push_back (
91+ SBInstructionToDisassembledInstruction (inst, resolveSymbols));
92+ --number_of_insts_before;
93+ }
94+ }
95+ }
96+
97+ // pad the instructions with invalid instructions if needed.
98+ for (size_t i = 0 ; i < number_of_insts_before &&
99+ instructions.size () < args.instructionCount ;
100+ ++i) {
101+ DisassembledInstruction invalid_inst;
102+ invalid_inst.presentationHint =
103+ DisassembledInstruction::eSourcePresentationHintInvalid;
104+ instructions.insert (instructions.begin (), std::move (invalid_inst));
105+ }
106+ }
107+
108+ const auto instructions_left = args.instructionCount - instructions.size ();
109+ lldb::SBInstructionList insts = dap.target .ReadInstructions (
110+ addr, instructions_left, flavor_string.c_str ());
59111 if (!insts.IsValid ())
60112 return llvm::make_error<DAPError>(
61113 " Failed to find instructions for memory address." );
62114
63- const bool resolveSymbols = args. resolveSymbols . value_or ( false );
115+ // add the disassembly from the given address forward
64116 const auto num_insts = insts.GetSize ();
65- for (size_t i = 0 ; i < num_insts; ++i) {
117+ for (size_t i = 0 ;
118+ i < num_insts && instructions.size () < args.instructionCount ; ++i) {
66119 lldb::SBInstruction inst = insts.GetInstructionAtIndex (i);
67- auto addr = inst.GetAddress ();
68- const auto inst_addr = addr.GetLoadAddress (dap.target );
69- const char *m = inst.GetMnemonic (dap.target );
70- const char *o = inst.GetOperands (dap.target );
71- const char *c = inst.GetComment (dap.target );
72- auto d = inst.GetData (dap.target );
73-
74- std::string bytes;
75- llvm::raw_string_ostream sb (bytes);
76- for (unsigned i = 0 ; i < inst.GetByteSize (); i++) {
77- lldb::SBError error;
78- uint8_t b = d.GetUnsignedInt8 (error, i);
79- if (error.Success ()) {
80- sb << llvm::format (" %2.2x " , b);
81- }
82- }
120+ instructions.push_back (
121+ SBInstructionToDisassembledInstruction (inst, resolveSymbols));
122+ }
83123
84- DisassembledInstruction disassembled_inst;
85- disassembled_inst.address = " 0x" + llvm::utohexstr (inst_addr);
86- disassembled_inst.instructionBytes =
87- bytes.size () > 0 ? bytes.substr (0 , bytes.size () - 1 ) : " " ;
88-
89- std::string instruction;
90- llvm::raw_string_ostream si (instruction);
91-
92- lldb::SBSymbol symbol = addr.GetSymbol ();
93- // Only add the symbol on the first line of the function.
94- if (symbol.IsValid () && symbol.GetStartAddress () == addr) {
95- // If we have a valid symbol, append it as a label prefix for the first
96- // instruction. This is so you can see the start of a function/callsite
97- // in the assembly, at the moment VS Code (1.80) does not visualize the
98- // symbol associated with the assembly instruction.
99- si << (symbol.GetMangledName () != nullptr ? symbol.GetMangledName ()
100- : symbol.GetName ())
101- << " : " ;
102-
103- if (resolveSymbols)
104- disassembled_inst.symbol = symbol.GetDisplayName ();
124+ // Pad the instructions with invalid instructions if needed.
125+ if (instructions.size () < args.instructionCount ) {
126+ for (size_t i = instructions.size (); i < args.instructionCount ; ++i) {
127+ DisassembledInstruction invalid_inst;
128+ invalid_inst.presentationHint =
129+ DisassembledInstruction::eSourcePresentationHintInvalid;
130+ instructions.push_back (std::move (invalid_inst));
105131 }
132+ }
133+
134+ return DisassembleResponseBody{std::move (instructions)};
135+ }
106136
107- si << llvm::formatv (" {0,7} {1,12}" , m, o);
108- if (c && c[0 ]) {
109- si << " ; " << c;
137+ DisassembledInstruction
138+ DisassembleRequestHandler::SBInstructionToDisassembledInstruction (
139+ lldb::SBInstruction &inst, bool resolveSymbols) const {
140+ auto addr = inst.GetAddress ();
141+ const auto inst_addr = addr.GetLoadAddress (dap.target );
142+ const char *m = inst.GetMnemonic (dap.target );
143+ const char *o = inst.GetOperands (dap.target );
144+ const char *c = inst.GetComment (dap.target );
145+ auto d = inst.GetData (dap.target );
146+
147+ std::string bytes;
148+ llvm::raw_string_ostream sb (bytes);
149+ for (unsigned i = 0 ; i < inst.GetByteSize (); i++) {
150+ lldb::SBError error;
151+ uint8_t b = d.GetUnsignedInt8 (error, i);
152+ if (error.Success ()) {
153+ sb << llvm::format (" %2.2x " , b);
110154 }
155+ }
111156
112- disassembled_inst.instruction = instruction;
113-
114- auto line_entry = addr.GetLineEntry ();
115- // If the line number is 0 then the entry represents a compiler generated
116- // location.
117- if (line_entry.GetStartAddress () == addr && line_entry.IsValid () &&
118- line_entry.GetFileSpec ().IsValid () && line_entry.GetLine () != 0 ) {
119- auto source = CreateSource (line_entry);
120- disassembled_inst.location = std::move (source);
121-
122- const auto line = line_entry.GetLine ();
123- if (line != 0 && line != LLDB_INVALID_LINE_NUMBER)
124- disassembled_inst.line = line;
125-
126- const auto column = line_entry.GetColumn ();
127- if (column != 0 && column != LLDB_INVALID_COLUMN_NUMBER)
128- disassembled_inst.column = column;
129-
130- auto end_line_entry = line_entry.GetEndAddress ().GetLineEntry ();
131- if (end_line_entry.IsValid () &&
132- end_line_entry.GetFileSpec () == line_entry.GetFileSpec ()) {
133- const auto end_line = end_line_entry.GetLine ();
134- if (end_line != 0 && end_line != LLDB_INVALID_LINE_NUMBER &&
135- end_line != line) {
136- disassembled_inst.endLine = end_line;
137-
138- const auto end_column = end_line_entry.GetColumn ();
139- if (end_column != 0 && end_column != LLDB_INVALID_COLUMN_NUMBER &&
140- end_column != column)
141- disassembled_inst.endColumn = end_column - 1 ;
142- }
157+ DisassembledInstruction disassembled_inst;
158+ disassembled_inst.address = " 0x" + llvm::utohexstr (inst_addr);
159+ disassembled_inst.instructionBytes =
160+ bytes.size () > 0 ? bytes.substr (0 , bytes.size () - 1 ) : " " ;
161+
162+ std::string instruction;
163+ llvm::raw_string_ostream si (instruction);
164+
165+ lldb::SBSymbol symbol = addr.GetSymbol ();
166+ // Only add the symbol on the first line of the function.
167+ if (symbol.IsValid () && symbol.GetStartAddress () == addr) {
168+ // If we have a valid symbol, append it as a label prefix for the first
169+ // instruction. This is so you can see the start of a function/callsite
170+ // in the assembly, at the moment VS Code (1.80) does not visualize the
171+ // symbol associated with the assembly instruction.
172+ si << (symbol.GetMangledName () != nullptr ? symbol.GetMangledName ()
173+ : symbol.GetName ())
174+ << " : " ;
175+
176+ if (resolveSymbols)
177+ disassembled_inst.symbol = symbol.GetDisplayName ();
178+ }
179+
180+ si << llvm::formatv (" {0,7} {1,12}" , m, o);
181+ if (c && c[0 ]) {
182+ si << " ; " << c;
183+ }
184+
185+ disassembled_inst.instruction = instruction;
186+
187+ auto line_entry = addr.GetLineEntry ();
188+ // If the line number is 0 then the entry represents a compiler generated
189+ // location.
190+ if (line_entry.GetStartAddress () == addr && line_entry.IsValid () &&
191+ line_entry.GetFileSpec ().IsValid () && line_entry.GetLine () != 0 ) {
192+ auto source = CreateSource (line_entry);
193+ disassembled_inst.location = std::move (source);
194+
195+ const auto line = line_entry.GetLine ();
196+ if (line != 0 && line != LLDB_INVALID_LINE_NUMBER)
197+ disassembled_inst.line = line;
198+
199+ const auto column = line_entry.GetColumn ();
200+ if (column != 0 && column != LLDB_INVALID_COLUMN_NUMBER)
201+ disassembled_inst.column = column;
202+
203+ auto end_line_entry = line_entry.GetEndAddress ().GetLineEntry ();
204+ if (end_line_entry.IsValid () &&
205+ end_line_entry.GetFileSpec () == line_entry.GetFileSpec ()) {
206+ const auto end_line = end_line_entry.GetLine ();
207+ if (end_line != 0 && end_line != LLDB_INVALID_LINE_NUMBER &&
208+ end_line != line) {
209+ disassembled_inst.endLine = end_line;
210+
211+ const auto end_column = end_line_entry.GetColumn ();
212+ if (end_column != 0 && end_column != LLDB_INVALID_COLUMN_NUMBER &&
213+ end_column != column)
214+ disassembled_inst.endColumn = end_column - 1 ;
143215 }
144216 }
145-
146- instructions.push_back (std::move (disassembled_inst));
147217 }
148218
149- return DisassembleResponseBody{ std::move (instructions)} ;
219+ return disassembled_inst ;
150220}
151221
152222} // namespace lldb_dap
0 commit comments