blob: 627374419df461bcc3e5a0c1401e7f0af51e9576 [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
Zachary Turner1f0f5b52016-09-22 20:22:55 +000037static OptionDefinition g_disassemble_options[] = {
38 // clang-format off
39 { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling." },
40 { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show." },
41 { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display." },
42 { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information." },
43 { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." },
44 { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
45 "Currently the only valid options are default, and for Intel "
46 "architectures, att and intel." },
47 { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." },
48 { LLDB_OPT_SET_1 |
49 LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." },
50 { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." },
51 { LLDB_OPT_SET_2 |
52 LLDB_OPT_SET_3 |
53 LLDB_OPT_SET_4 |
54 LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display." },
55 { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." },
56 { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." },
57 { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc." },
58 { 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 "
59 "table information, else disassemble around the pc." },
60 { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." },
61 // clang-format on
62};
63
Kate Stoneb9c1b512016-09-06 20:57:50 +000064CommandObjectDisassemble::CommandOptions::CommandOptions()
65 : Options(), num_lines_context(0), num_instructions(0), func_name(),
66 current_function(false), start_addr(), end_addr(), at_pc(false),
67 frame_line(false), plugin_name(), flavor_string(), arch(),
68 some_location_specified(false), symbol_containing_addr() {
69 OptionParsingStarting(nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070}
71
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000072CommandObjectDisassemble::CommandOptions::~CommandOptions() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073
Kate Stoneb9c1b512016-09-06 20:57:50 +000074Error CommandObjectDisassemble::CommandOptions::SetOptionValue(
75 uint32_t option_idx, const char *option_arg,
76 ExecutionContext *execution_context) {
77 Error error;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 bool success;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 switch (short_option) {
84 case 'm':
85 show_mixed = true;
86 break;
Jim Ingham37023b02011-03-22 01:48:42 +000087
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 case 'C':
89 num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success);
90 if (!success)
91 error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"",
92 option_arg);
93 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 case 'c':
96 num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success);
97 if (!success)
98 error.SetErrorStringWithFormat(
99 "invalid num of instructions string: \"%s\"", option_arg);
100 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 case 'b':
103 show_bytes = true;
104 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000105
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 case 's': {
107 start_addr = Args::StringToAddress(execution_context, option_arg,
108 LLDB_INVALID_ADDRESS, &error);
109 if (start_addr != LLDB_INVALID_ADDRESS)
110 some_location_specified = true;
111 } break;
112 case 'e': {
113 end_addr = Args::StringToAddress(execution_context, option_arg,
114 LLDB_INVALID_ADDRESS, &error);
115 if (end_addr != LLDB_INVALID_ADDRESS)
116 some_location_specified = true;
117 } break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 case 'n':
120 func_name.assign(option_arg);
121 some_location_specified = true;
122 break;
Greg Clayton32e0a752011-03-30 18:16:51 +0000123
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 case 'p':
125 at_pc = true;
126 some_location_specified = true;
127 break;
Jim Ingham37023b02011-03-22 01:48:42 +0000128
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129 case 'l':
130 frame_line = true;
131 // Disassemble the current source line kind of implies showing mixed
132 // source code context.
133 show_mixed = true;
134 some_location_specified = true;
135 break;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137 case 'P':
138 plugin_name.assign(option_arg);
139 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000140
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 case 'F': {
142 TargetSP target_sp =
143 execution_context ? execution_context->GetTargetSP() : TargetSP();
144 if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() ==
145 llvm::Triple::x86 ||
146 target_sp->GetArchitecture().GetTriple().getArch() ==
147 llvm::Triple::x86_64)) {
148 flavor_string.assign(option_arg);
149 } else
150 error.SetErrorStringWithFormat("Disassembler flavors are currently only "
151 "supported for x86 and x86_64 targets.");
152 break;
153 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 case 'r':
156 raw = true;
157 break;
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000158
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159 case 'f':
160 current_function = true;
161 some_location_specified = true;
162 break;
Greg Clayton357132e2011-03-26 19:14:58 +0000163
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164 case 'A':
165 if (execution_context) {
166 auto target_sp =
167 execution_context ? execution_context->GetTargetSP() : TargetSP();
168 auto platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
169 if (!arch.SetTriple(option_arg, platform_sp.get()))
170 arch.SetTriple(option_arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000171 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 case 'a': {
175 symbol_containing_addr = Args::StringToAddress(
176 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
177 if (symbol_containing_addr != LLDB_INVALID_ADDRESS) {
178 some_location_specified = true;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000179 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 } break;
181
182 default:
183 error.SetErrorStringWithFormat("unrecognized short option '%c'",
184 short_option);
185 break;
186 }
187
188 return error;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000189}
190
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
192 ExecutionContext *execution_context) {
193 show_mixed = false;
194 show_bytes = false;
195 num_lines_context = 0;
196 num_instructions = 0;
197 func_name.clear();
198 current_function = false;
199 at_pc = false;
200 frame_line = false;
201 start_addr = LLDB_INVALID_ADDRESS;
202 end_addr = LLDB_INVALID_ADDRESS;
203 symbol_containing_addr = LLDB_INVALID_ADDRESS;
204 raw = false;
205 plugin_name.clear();
206
207 Target *target =
208 execution_context ? execution_context->GetTargetPtr() : nullptr;
209
210 // This is a hack till we get the ability to specify features based on
211 // architecture. For now GetDisassemblyFlavor
212 // is really only valid for x86 (and for the llvm assembler plugin, but I'm
213 // papering over that since that is the
214 // only disassembler plugin we have...
215 if (target) {
216 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
217 target->GetArchitecture().GetTriple().getArch() ==
218 llvm::Triple::x86_64) {
219 flavor_string.assign(target->GetDisassemblyFlavor());
220 } else
221 flavor_string.assign("default");
222
223 } else
224 flavor_string.assign("default");
225
226 arch.Clear();
227 some_location_specified = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228}
229
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230Error CommandObjectDisassemble::CommandOptions::OptionParsingFinished(
231 ExecutionContext *execution_context) {
232 if (!some_location_specified)
233 current_function = true;
Mehdi Amini41af4302016-11-11 04:28:40 +0000234 return Error::success();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235}
236
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000237llvm::ArrayRef<OptionDefinition>
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238CommandObjectDisassemble::CommandOptions::GetDefinitions() {
Zachary Turner70602432016-09-22 21:06:13 +0000239 return llvm::makeArrayRef(g_disassemble_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240}
241
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000242//-------------------------------------------------------------------------
243// CommandObjectDisassemble
244//-------------------------------------------------------------------------
245
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246CommandObjectDisassemble::CommandObjectDisassemble(
247 CommandInterpreter &interpreter)
248 : CommandObjectParsed(
249 interpreter, "disassemble",
250 "Disassemble specified instructions in the current target. "
251 "Defaults to the current function for the current thread and "
252 "stack frame.",
253 "disassemble [<cmd-options>]"),
254 m_options() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000256CommandObjectDisassemble::~CommandObjectDisassemble() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258bool CommandObjectDisassemble::DoExecute(Args &command,
259 CommandReturnObject &result) {
260 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
261 if (target == nullptr) {
262 result.AppendError("invalid target, create a debug target using the "
263 "'target create' command");
264 result.SetStatus(eReturnStatusFailed);
265 return false;
266 }
267 if (!m_options.arch.IsValid())
268 m_options.arch = target->GetArchitecture();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 if (!m_options.arch.IsValid()) {
271 result.AppendError(
272 "use the --arch option or set the target architecture to disassemble");
273 result.SetStatus(eReturnStatusFailed);
274 return false;
275 }
276
277 const char *plugin_name = m_options.GetPluginName();
278 const char *flavor_string = m_options.GetFlavorString();
279
280 DisassemblerSP disassembler =
281 Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
282
283 if (!disassembler) {
284 if (plugin_name) {
285 result.AppendErrorWithFormat(
286 "Unable to find Disassembler plug-in named '%s' that supports the "
287 "'%s' architecture.\n",
288 plugin_name, m_options.arch.GetArchitectureName());
289 } else
290 result.AppendErrorWithFormat(
291 "Unable to find Disassembler plug-in for the '%s' architecture.\n",
292 m_options.arch.GetArchitectureName());
293 result.SetStatus(eReturnStatusFailed);
294 return false;
295 } else if (flavor_string != nullptr &&
296 !disassembler->FlavorValidForArchSpec(m_options.arch,
297 flavor_string))
298 result.AppendWarningWithFormat(
299 "invalid disassembler flavor \"%s\", using default.\n", flavor_string);
300
301 result.SetStatus(eReturnStatusSuccessFinishResult);
302
Zachary Turner11eb9c62016-10-05 20:03:37 +0000303 if (!command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 result.AppendErrorWithFormat(
305 "\"disassemble\" arguments are specified as options.\n");
306 const int terminal_width =
307 GetCommandInterpreter().GetDebugger().GetTerminalWidth();
308 GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
309 terminal_width);
310 result.SetStatus(eReturnStatusFailed);
311 return false;
312 }
313
314 if (m_options.show_mixed && m_options.num_lines_context == 0)
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000315 m_options.num_lines_context = 2;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316
317 // Always show the PC in the disassembly
318 uint32_t options = Disassembler::eOptionMarkPCAddress;
319
320 // Mark the source line for the current PC only if we are doing mixed source
321 // and assembly
322 if (m_options.show_mixed)
323 options |= Disassembler::eOptionMarkPCSourceLine;
324
325 if (m_options.show_bytes)
326 options |= Disassembler::eOptionShowBytes;
327
328 if (m_options.raw)
329 options |= Disassembler::eOptionRawOuput;
330
331 if (!m_options.func_name.empty()) {
332 ConstString name(m_options.func_name.c_str());
333
334 if (Disassembler::Disassemble(
335 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
336 flavor_string, m_exe_ctx, name,
337 nullptr, // Module *
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000338 m_options.num_instructions, m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339 m_options.show_mixed ? m_options.num_lines_context : 0, options,
340 result.GetOutputStream())) {
341 result.SetStatus(eReturnStatusSuccessFinishResult);
342 } else {
343 result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n",
344 name.GetCString());
345 result.SetStatus(eReturnStatusFailed);
346 }
347 } else {
348 std::vector<AddressRange> ranges;
349 AddressRange range;
350 StackFrame *frame = m_exe_ctx.GetFramePtr();
351 if (m_options.frame_line) {
352 if (frame == nullptr) {
353 result.AppendError("Cannot disassemble around the current line without "
354 "a selected frame.\n");
355 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 }
358 LineEntry pc_line_entry(
359 frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
360 if (pc_line_entry.IsValid()) {
361 range = pc_line_entry.range;
362 } else {
363 m_options.at_pc =
364 true; // No line entry, so just disassemble around the current pc
365 m_options.show_mixed = false;
366 }
367 } else if (m_options.current_function) {
368 if (frame == nullptr) {
369 result.AppendError("Cannot disassemble around the current function "
370 "without a selected frame.\n");
371 result.SetStatus(eReturnStatusFailed);
372 return false;
373 }
374 Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
375 if (symbol) {
376 range.GetBaseAddress() = symbol->GetAddress();
377 range.SetByteSize(symbol->GetByteSize());
378 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379 }
380
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381 // Did the "m_options.frame_line" find a valid range already? If so
382 // skip the rest...
383 if (range.GetByteSize() == 0) {
384 if (m_options.at_pc) {
385 if (frame == nullptr) {
386 result.AppendError("Cannot disassemble around the current PC without "
387 "a selected frame.\n");
388 result.SetStatus(eReturnStatusFailed);
389 return false;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000390 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391 range.GetBaseAddress() = frame->GetFrameCodeAddress();
392 if (m_options.num_instructions == 0) {
393 // Disassembling at the PC always disassembles some number of
394 // instructions (not the whole function).
395 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 ranges.push_back(range);
398 } else {
399 range.GetBaseAddress().SetOffset(m_options.start_addr);
400 if (range.GetBaseAddress().IsValid()) {
401 if (m_options.end_addr != LLDB_INVALID_ADDRESS) {
402 if (m_options.end_addr <= m_options.start_addr) {
403 result.AppendErrorWithFormat(
404 "End address before start address.\n");
405 result.SetStatus(eReturnStatusFailed);
406 return false;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000407 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408 range.SetByteSize(m_options.end_addr - m_options.start_addr);
409 }
410 ranges.push_back(range);
411 } else {
412 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS &&
413 target) {
414 if (!target->GetSectionLoadList().IsEmpty()) {
415 bool failed = false;
416 Address symbol_containing_address;
417 if (target->GetSectionLoadList().ResolveLoadAddress(
418 m_options.symbol_containing_addr,
419 symbol_containing_address)) {
420 ModuleSP module_sp(symbol_containing_address.GetModule());
421 SymbolContext sc;
422 bool resolve_tail_call_address = true; // PC can be one past the
423 // address range of the
424 // function.
425 module_sp->ResolveSymbolContextForAddress(
426 symbol_containing_address, eSymbolContextEverything, sc,
427 resolve_tail_call_address);
428 if (sc.function || sc.symbol) {
429 sc.GetAddressRange(eSymbolContextFunction |
430 eSymbolContextSymbol,
431 0, false, range);
432 } else {
433 failed = true;
Greg Clayton32e0a752011-03-30 18:16:51 +0000434 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000435 } else {
436 failed = true;
437 }
438 if (failed) {
439 result.AppendErrorWithFormat(
440 "Could not find function bounds for address 0x%" PRIx64
441 "\n",
442 m_options.symbol_containing_addr);
443 result.SetStatus(eReturnStatusFailed);
444 return false;
445 }
446 ranges.push_back(range);
447 } else {
448 for (lldb::ModuleSP module_sp : target->GetImages().Modules()) {
449 lldb::addr_t file_addr = m_options.symbol_containing_addr;
450 Address file_address;
451 if (module_sp->ResolveFileAddress(file_addr, file_address)) {
452 SymbolContext sc;
453 bool resolve_tail_call_address = true; // PC can be one past
454 // the address range of
455 // the function.
456 module_sp->ResolveSymbolContextForAddress(
457 file_address, eSymbolContextEverything, sc,
458 resolve_tail_call_address);
459 if (sc.function || sc.symbol) {
460 sc.GetAddressRange(eSymbolContextFunction |
461 eSymbolContextSymbol,
462 0, false, range);
Jim Ingham2f4693a2014-04-03 17:16:17 +0000463 ranges.push_back(range);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464 }
Jim Ingham37023b02011-03-22 01:48:42 +0000465 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 }
Jim Ingham37023b02011-03-22 01:48:42 +0000467 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 }
Jim Ingham37023b02011-03-22 01:48:42 +0000469 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 }
471 } else
472 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000473
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 if (m_options.num_instructions != 0) {
475 if (ranges.empty()) {
476 // The default action is to disassemble the current frame function.
477 if (frame) {
478 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
479 eSymbolContextSymbol));
480 if (sc.function)
481 range.GetBaseAddress() =
482 sc.function->GetAddressRange().GetBaseAddress();
483 else if (sc.symbol && sc.symbol->ValueIsAddress())
484 range.GetBaseAddress() = sc.symbol->GetAddress();
485 else
486 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000487 }
Jim Ingham37023b02011-03-22 01:48:42 +0000488
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489 if (!range.GetBaseAddress().IsValid()) {
490 result.AppendError("invalid frame");
491 result.SetStatus(eReturnStatusFailed);
492 return false;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000493 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000494 }
495
496 bool print_sc_header = ranges.size() > 1;
497 for (AddressRange cur_range : ranges) {
498 if (Disassembler::Disassemble(
499 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
500 flavor_string, m_exe_ctx, cur_range.GetBaseAddress(),
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000501 m_options.num_instructions, m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000502 m_options.show_mixed ? m_options.num_lines_context : 0, options,
503 result.GetOutputStream())) {
504 result.SetStatus(eReturnStatusSuccessFinishResult);
505 } else {
506 if (m_options.start_addr != LLDB_INVALID_ADDRESS)
507 result.AppendErrorWithFormat(
508 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
509 m_options.start_addr);
510 else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
511 result.AppendErrorWithFormat(
512 "Failed to disassemble memory in function at 0x%8.8" PRIx64
513 ".\n",
514 m_options.symbol_containing_addr);
515 result.SetStatus(eReturnStatusFailed);
516 }
517 }
518 if (print_sc_header)
519 result.AppendMessage("\n");
520 } else {
521 if (ranges.empty()) {
522 // The default action is to disassemble the current frame function.
523 if (frame) {
524 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
525 eSymbolContextSymbol));
526 if (sc.function)
527 range = sc.function->GetAddressRange();
528 else if (sc.symbol && sc.symbol->ValueIsAddress()) {
529 range.GetBaseAddress() = sc.symbol->GetAddress();
530 range.SetByteSize(sc.symbol->GetByteSize());
531 } else
532 range.GetBaseAddress() = frame->GetFrameCodeAddress();
533 } else {
534 result.AppendError("invalid frame");
535 result.SetStatus(eReturnStatusFailed);
536 return false;
537 }
538 ranges.push_back(range);
539 }
540
541 bool print_sc_header = ranges.size() > 1;
542 for (AddressRange cur_range : ranges) {
543 if (cur_range.GetByteSize() == 0)
544 cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
545
546 if (Disassembler::Disassemble(
547 m_interpreter.GetDebugger(), m_options.arch, plugin_name,
548 flavor_string, m_exe_ctx, cur_range, m_options.num_instructions,
Jason Molenda0b4c26b2016-09-08 05:12:41 +0000549 m_options.show_mixed,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 m_options.show_mixed ? m_options.num_lines_context : 0, options,
551 result.GetOutputStream())) {
552 result.SetStatus(eReturnStatusSuccessFinishResult);
553 } else {
554 result.AppendErrorWithFormat(
555 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
556 m_options.start_addr);
557 result.SetStatus(eReturnStatusFailed);
558 }
559 if (print_sc_header)
560 result.AppendMessage("\n");
561 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000562 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000564
Kate Stoneb9c1b512016-09-06 20:57:50 +0000565 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000566}