blob: 8dbcc3ef0afae9e3f77c115fc6cdacc9ba21b1fb [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000014#include "CommandObjectDisassemble.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Core/AddressRange.h"
Greg Clayton1f746072012-08-29 21:13:06 +000016#include "lldb/Core/Disassembler.h"
Jason Molenda801237a2013-04-11 03:14:01 +000017#include "lldb/Core/Module.h"
Greg Clayton1f746072012-08-29 21:13:06 +000018#include "lldb/Core/SourceManager.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000019#include "lldb/Host/StringConvert.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Interpreter/CommandCompletions.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000023#include "lldb/Interpreter/Options.h"
Greg Clayton1f746072012-08-29 21:13:06 +000024#include "lldb/Symbol/Function.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Symbol/Symbol.h"
26#include "lldb/Target/Process.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000027#include "lldb/Target/SectionLoadList.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000028#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Target/Target.h"
30
31#define DEFAULT_DISASM_BYTE_SIZE 32
Kate Stoneb9c1b512016-09-06 20:57:50 +000032#define DEFAULT_DISASM_NUM_INS 4
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037CommandObjectDisassemble::CommandOptions::CommandOptions()
38 : Options(), num_lines_context(0), num_instructions(0), func_name(),
39 current_function(false), start_addr(), end_addr(), at_pc(false),
40 frame_line(false), plugin_name(), flavor_string(), arch(),
41 some_location_specified(false), symbol_containing_addr() {
42 OptionParsingStarting(nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000045CommandObjectDisassemble::CommandOptions::~CommandOptions() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046
Kate Stoneb9c1b512016-09-06 20:57:50 +000047Error CommandObjectDisassemble::CommandOptions::SetOptionValue(
48 uint32_t option_idx, const char *option_arg,
49 ExecutionContext *execution_context) {
50 Error error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 bool success;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 switch (short_option) {
57 case 'm':
58 show_mixed = true;
59 break;
Jim Ingham37023b02011-03-22 01:48:42 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 case 'C':
62 num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success);
63 if (!success)
64 error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"",
65 option_arg);
66 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 case 'c':
69 num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success);
70 if (!success)
71 error.SetErrorStringWithFormat(
72 "invalid num of instructions string: \"%s\"", option_arg);
73 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074
Kate Stoneb9c1b512016-09-06 20:57:50 +000075 case 'b':
76 show_bytes = true;
77 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000078
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 case 's': {
80 start_addr = Args::StringToAddress(execution_context, option_arg,
81 LLDB_INVALID_ADDRESS, &error);
82 if (start_addr != LLDB_INVALID_ADDRESS)
83 some_location_specified = true;
84 } break;
85 case 'e': {
86 end_addr = Args::StringToAddress(execution_context, option_arg,
87 LLDB_INVALID_ADDRESS, &error);
88 if (end_addr != LLDB_INVALID_ADDRESS)
89 some_location_specified = true;
90 } break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091
Kate Stoneb9c1b512016-09-06 20:57:50 +000092 case 'n':
93 func_name.assign(option_arg);
94 some_location_specified = true;
95 break;
Greg Clayton32e0a752011-03-30 18:16:51 +000096
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 case 'p':
98 at_pc = true;
99 some_location_specified = true;
100 break;
Jim Ingham37023b02011-03-22 01:48:42 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 case 'l':
103 frame_line = true;
104 // Disassemble the current source line kind of implies showing mixed
105 // source code context.
106 show_mixed = true;
107 some_location_specified = true;
108 break;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 case 'P':
111 plugin_name.assign(option_arg);
112 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000113
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114 case 'F': {
115 TargetSP target_sp =
116 execution_context ? execution_context->GetTargetSP() : TargetSP();
117 if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() ==
118 llvm::Triple::x86 ||
119 target_sp->GetArchitecture().GetTriple().getArch() ==
120 llvm::Triple::x86_64)) {
121 flavor_string.assign(option_arg);
122 } else
123 error.SetErrorStringWithFormat("Disassembler flavors are currently only "
124 "supported for x86 and x86_64 targets.");
125 break;
126 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000127
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 case 'r':
129 raw = true;
130 break;
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000131
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132 case 'f':
133 current_function = true;
134 some_location_specified = true;
135 break;
Greg Clayton357132e2011-03-26 19:14:58 +0000136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 case 'A':
138 if (execution_context) {
139 auto target_sp =
140 execution_context ? execution_context->GetTargetSP() : TargetSP();
141 auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
142 if (!arch.SetTriple(option_arg, platform_sp.get()))
143 arch.SetTriple(option_arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000144 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 case 'a': {
148 symbol_containing_addr = Args::StringToAddress(
149 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
150 if (symbol_containing_addr != LLDB_INVALID_ADDRESS) {
151 some_location_specified = true;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000152 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153 } break;
154
155 default:
156 error.SetErrorStringWithFormat("unrecognized short option '%c'",
157 short_option);
158 break;
159 }
160
161 return error;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000162}
163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
165 ExecutionContext *execution_context) {
166 show_mixed = false;
167 show_bytes = false;
168 num_lines_context = 0;
169 num_instructions = 0;
170 func_name.clear();
171 current_function = false;
172 at_pc = false;
173 frame_line = false;
174 start_addr = LLDB_INVALID_ADDRESS;
175 end_addr = LLDB_INVALID_ADDRESS;
176 symbol_containing_addr = LLDB_INVALID_ADDRESS;
177 raw = false;
178 plugin_name.clear();
179
180 Target *target =
181 execution_context ? execution_context->GetTargetPtr() : nullptr;
182
183 // This is a hack till we get the ability to specify features based on
184 // architecture. For now GetDisassemblyFlavor
185 // is really only valid for x86 (and for the llvm assembler plugin, but I'm
186 // papering over that since that is the
187 // only disassembler plugin we have...
188 if (target) {
189 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
190 target->GetArchitecture().GetTriple().getArch() ==
191 llvm::Triple::x86_64) {
192 flavor_string.assign(target->GetDisassemblyFlavor());
193 } else
194 flavor_string.assign("default");
195
196 } else
197 flavor_string.assign("default");
198
199 arch.Clear();
200 some_location_specified = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201}
202
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203Error CommandObjectDisassemble::CommandOptions::OptionParsingFinished(
204 ExecutionContext *execution_context) {
205 if (!some_location_specified)
206 current_function = true;
207 return Error();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000208}
209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210const OptionDefinition *
211CommandObjectDisassemble::CommandOptions::GetDefinitions() {
212 return g_option_table;
213}
214
215OptionDefinition CommandObjectDisassemble::CommandOptions::g_option_table[] = {
216 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000217 {LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
218 {LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."},
219 {LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."},
220 {LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
221 {LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
222 {LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
223 "Currently the only valid options are default, and for Intel "
224 "architectures, att and intel."},
225 {LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly."},
226 {LLDB_OPT_SET_1 |
227 LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling."},
228 {LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
229 {LLDB_OPT_SET_2 |
230 LLDB_OPT_SET_3 |
231 LLDB_OPT_SET_4 |
232 LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."},
233 {LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
234 {LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
235 {LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc."},
236 {LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line "
237 "table information, else disassemble around the pc."},
238 {LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
239 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 // clang-format on
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000241};
242
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243//-------------------------------------------------------------------------
244// CommandObjectDisassemble
245//-------------------------------------------------------------------------
246
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247CommandObjectDisassemble::CommandObjectDisassemble(
248 CommandInterpreter &interpreter)
249 : CommandObjectParsed(
250 interpreter, "disassemble",
251 "Disassemble specified instructions in the current target. "
252 "Defaults to the current function for the current thread and "
253 "stack frame.",
254 "disassemble [<cmd-options>]"),
255 m_options() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000257CommandObjectDisassemble::~CommandObjectDisassemble() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259bool CommandObjectDisassemble::DoExecute(Args &command,
260 CommandReturnObject &result) {
261 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
262 if (target == nullptr) {
263 result.AppendError("invalid target, create a debug target using the "
264 "'target create' command");
265 result.SetStatus(eReturnStatusFailed);
266 return false;
267 }
268 if (!m_options.arch.IsValid())
269 m_options.arch = target->GetArchitecture();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271 if (!m_options.arch.IsValid()) {
272 result.AppendError(
273 "use the --arch option or set the target architecture to disassemble");
274 result.SetStatus(eReturnStatusFailed);
275 return false;
276 }
277
278 const char *plugin_name = m_options.GetPluginName();
279 const char *flavor_string = m_options.GetFlavorString();
280
281 DisassemblerSP disassembler =
282 Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
283
284 if (!disassembler) {
285 if (plugin_name) {
286 result.AppendErrorWithFormat(
287 "Unable to find Disassembler plug-in named '%s' that supports the "
288 "'%s' architecture.\n",
289 plugin_name, m_options.arch.GetArchitectureName());
290 } else
291 result.AppendErrorWithFormat(
292 "Unable to find Disassembler plug-in for the '%s' architecture.\n",
293 m_options.arch.GetArchitectureName());
294 result.SetStatus(eReturnStatusFailed);
295 return false;
296 } else if (flavor_string != nullptr &&
297 !disassembler->FlavorValidForArchSpec(m_options.arch,
298 flavor_string))
299 result.AppendWarningWithFormat(
300 "invalid disassembler flavor \"%s\", using default.\n", flavor_string);
301
302 result.SetStatus(eReturnStatusSuccessFinishResult);
303
304 if (command.GetArgumentCount() != 0) {
305 result.AppendErrorWithFormat(
306 "\"disassemble\" arguments are specified as options.\n");
307 const int terminal_width =
308 GetCommandInterpreter().GetDebugger().GetTerminalWidth();
309 GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
310 terminal_width);
311 result.SetStatus(eReturnStatusFailed);
312 return false;
313 }
314
315 if (m_options.show_mixed && m_options.num_lines_context == 0)
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000316 m_options.num_lines_context = 2;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317
318 // Always show the PC in the disassembly
319 uint32_t options = Disassembler::eOptionMarkPCAddress;
320
321 // Mark the source line for the current PC only if we are doing mixed source
322 // and assembly
323 if (m_options.show_mixed)
324 options |= Disassembler::eOptionMarkPCSourceLine;
325
326 if (m_options.show_bytes)
327 options |= Disassembler::eOptionShowBytes;
328
329 if (m_options.raw)
330 options |= Disassembler::eOptionRawOuput;
331
332 if (!m_options.func_name.empty()) {
333 ConstString name(m_options.func_name.c_str());
334
335 if (Disassembler::Disassemble(
336 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
337 flavor_string, m_exe_ctx, name,
338 nullptr, // Module *
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000339 m_options.num_instructions, m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 m_options.show_mixed ? m_options.num_lines_context : 0, options,
341 result.GetOutputStream())) {
342 result.SetStatus(eReturnStatusSuccessFinishResult);
343 } else {
344 result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n",
345 name.GetCString());
346 result.SetStatus(eReturnStatusFailed);
347 }
348 } else {
349 std::vector<AddressRange> ranges;
350 AddressRange range;
351 StackFrame *frame = m_exe_ctx.GetFramePtr();
352 if (m_options.frame_line) {
353 if (frame == nullptr) {
354 result.AppendError("Cannot disassemble around the current line without "
355 "a selected frame.\n");
356 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 }
359 LineEntry pc_line_entry(
360 frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
361 if (pc_line_entry.IsValid()) {
362 range = pc_line_entry.range;
363 } else {
364 m_options.at_pc =
365 true; // No line entry, so just disassemble around the current pc
366 m_options.show_mixed = false;
367 }
368 } else if (m_options.current_function) {
369 if (frame == nullptr) {
370 result.AppendError("Cannot disassemble around the current function "
371 "without a selected frame.\n");
372 result.SetStatus(eReturnStatusFailed);
373 return false;
374 }
375 Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
376 if (symbol) {
377 range.GetBaseAddress() = symbol->GetAddress();
378 range.SetByteSize(symbol->GetByteSize());
379 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 }
381
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382 // Did the "m_options.frame_line" find a valid range already? If so
383 // skip the rest...
384 if (range.GetByteSize() == 0) {
385 if (m_options.at_pc) {
386 if (frame == nullptr) {
387 result.AppendError("Cannot disassemble around the current PC without "
388 "a selected frame.\n");
389 result.SetStatus(eReturnStatusFailed);
390 return false;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000391 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000392 range.GetBaseAddress() = frame->GetFrameCodeAddress();
393 if (m_options.num_instructions == 0) {
394 // Disassembling at the PC always disassembles some number of
395 // instructions (not the whole function).
396 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398 ranges.push_back(range);
399 } else {
400 range.GetBaseAddress().SetOffset(m_options.start_addr);
401 if (range.GetBaseAddress().IsValid()) {
402 if (m_options.end_addr != LLDB_INVALID_ADDRESS) {
403 if (m_options.end_addr <= m_options.start_addr) {
404 result.AppendErrorWithFormat(
405 "End address before start address.\n");
406 result.SetStatus(eReturnStatusFailed);
407 return false;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000408 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000409 range.SetByteSize(m_options.end_addr - m_options.start_addr);
410 }
411 ranges.push_back(range);
412 } else {
413 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS &&
414 target) {
415 if (!target->GetSectionLoadList().IsEmpty()) {
416 bool failed = false;
417 Address symbol_containing_address;
418 if (target->GetSectionLoadList().ResolveLoadAddress(
419 m_options.symbol_containing_addr,
420 symbol_containing_address)) {
421 ModuleSP module_sp(symbol_containing_address.GetModule());
422 SymbolContext sc;
423 bool resolve_tail_call_address = true; // PC can be one past the
424 // address range of the
425 // function.
426 module_sp->ResolveSymbolContextForAddress(
427 symbol_containing_address, eSymbolContextEverything, sc,
428 resolve_tail_call_address);
429 if (sc.function || sc.symbol) {
430 sc.GetAddressRange(eSymbolContextFunction |
431 eSymbolContextSymbol,
432 0, false, range);
433 } else {
434 failed = true;
Greg Clayton32e0a752011-03-30 18:16:51 +0000435 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000436 } else {
437 failed = true;
438 }
439 if (failed) {
440 result.AppendErrorWithFormat(
441 "Could not find function bounds for address 0x%" PRIx64
442 "\n",
443 m_options.symbol_containing_addr);
444 result.SetStatus(eReturnStatusFailed);
445 return false;
446 }
447 ranges.push_back(range);
448 } else {
449 for (lldb::ModuleSP module_sp : target->GetImages().Modules()) {
450 lldb::addr_t file_addr = m_options.symbol_containing_addr;
451 Address file_address;
452 if (module_sp->ResolveFileAddress(file_addr, file_address)) {
453 SymbolContext sc;
454 bool resolve_tail_call_address = true; // PC can be one past
455 // the address range of
456 // the function.
457 module_sp->ResolveSymbolContextForAddress(
458 file_address, eSymbolContextEverything, sc,
459 resolve_tail_call_address);
460 if (sc.function || sc.symbol) {
461 sc.GetAddressRange(eSymbolContextFunction |
462 eSymbolContextSymbol,
463 0, false, range);
Jim Ingham2f4693a2014-04-03 17:16:17 +0000464 ranges.push_back(range);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465 }
Jim Ingham37023b02011-03-22 01:48:42 +0000466 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000467 }
Jim Ingham37023b02011-03-22 01:48:42 +0000468 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469 }
Jim Ingham37023b02011-03-22 01:48:42 +0000470 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 }
472 } else
473 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000474
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 if (m_options.num_instructions != 0) {
476 if (ranges.empty()) {
477 // The default action is to disassemble the current frame function.
478 if (frame) {
479 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
480 eSymbolContextSymbol));
481 if (sc.function)
482 range.GetBaseAddress() =
483 sc.function->GetAddressRange().GetBaseAddress();
484 else if (sc.symbol && sc.symbol->ValueIsAddress())
485 range.GetBaseAddress() = sc.symbol->GetAddress();
486 else
487 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000488 }
Jim Ingham37023b02011-03-22 01:48:42 +0000489
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490 if (!range.GetBaseAddress().IsValid()) {
491 result.AppendError("invalid frame");
492 result.SetStatus(eReturnStatusFailed);
493 return false;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000494 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 }
496
497 bool print_sc_header = ranges.size() > 1;
498 for (AddressRange cur_range : ranges) {
499 if (Disassembler::Disassemble(
500 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
501 flavor_string, m_exe_ctx, cur_range.GetBaseAddress(),
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000502 m_options.num_instructions, m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000503 m_options.show_mixed ? m_options.num_lines_context : 0, options,
504 result.GetOutputStream())) {
505 result.SetStatus(eReturnStatusSuccessFinishResult);
506 } else {
507 if (m_options.start_addr != LLDB_INVALID_ADDRESS)
508 result.AppendErrorWithFormat(
509 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
510 m_options.start_addr);
511 else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
512 result.AppendErrorWithFormat(
513 "Failed to disassemble memory in function at 0x%8.8" PRIx64
514 ".\n",
515 m_options.symbol_containing_addr);
516 result.SetStatus(eReturnStatusFailed);
517 }
518 }
519 if (print_sc_header)
520 result.AppendMessage("\n");
521 } else {
522 if (ranges.empty()) {
523 // The default action is to disassemble the current frame function.
524 if (frame) {
525 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
526 eSymbolContextSymbol));
527 if (sc.function)
528 range = sc.function->GetAddressRange();
529 else if (sc.symbol && sc.symbol->ValueIsAddress()) {
530 range.GetBaseAddress() = sc.symbol->GetAddress();
531 range.SetByteSize(sc.symbol->GetByteSize());
532 } else
533 range.GetBaseAddress() = frame->GetFrameCodeAddress();
534 } else {
535 result.AppendError("invalid frame");
536 result.SetStatus(eReturnStatusFailed);
537 return false;
538 }
539 ranges.push_back(range);
540 }
541
542 bool print_sc_header = ranges.size() > 1;
543 for (AddressRange cur_range : ranges) {
544 if (cur_range.GetByteSize() == 0)
545 cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
546
547 if (Disassembler::Disassemble(
548 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
549 flavor_string, m_exe_ctx, cur_range, m_options.num_instructions,
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000550 m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000551 m_options.show_mixed ? m_options.num_lines_context : 0, options,
552 result.GetOutputStream())) {
553 result.SetStatus(eReturnStatusSuccessFinishResult);
554 } else {
555 result.AppendErrorWithFormat(
556 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
557 m_options.start_addr);
558 result.SetStatus(eReturnStatusFailed);
559 }
560 if (print_sc_header)
561 result.AppendMessage("\n");
562 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000563 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000564 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000567}