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