130fdc8d8SChris Lattner //===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
926cac3afSEugene Zelenko #include "CommandObjectDisassemble.h"
1030fdc8d8SChris Lattner #include "lldb/Core/AddressRange.h"
111f746071SGreg Clayton #include "lldb/Core/Disassembler.h"
12801237a2SJason Molenda #include "lldb/Core/Module.h"
131f746071SGreg Clayton #include "lldb/Core/SourceManager.h"
143eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h"
1530fdc8d8SChris Lattner #include "lldb/Interpreter/CommandCompletions.h"
1630fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
1730fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
1847cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h"
1940af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
201f746071SGreg Clayton #include "lldb/Symbol/Function.h"
2130fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h"
2230fdc8d8SChris Lattner #include "lldb/Target/Process.h"
23d5944cd1SGreg Clayton #include "lldb/Target/SectionLoadList.h"
24b57e4a1bSJason Molenda #include "lldb/Target/StackFrame.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32
2837023b06SJim Ingham #define DEFAULT_DISASM_NUM_INS 4
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner using namespace lldb;
3130fdc8d8SChris Lattner using namespace lldb_private;
3230fdc8d8SChris Lattner 
33f1883637SRaphael Isemann #define LLDB_OPTIONS_disassemble
34f1883637SRaphael Isemann #include "CommandOptions.inc"
351f0f5b5bSZachary Turner 
36b9c1b51eSKate Stone CommandObjectDisassemble::CommandOptions::CommandOptions()
37b9c1b51eSKate Stone     : Options(), num_lines_context(0), num_instructions(0), func_name(),
38b9c1b51eSKate Stone       current_function(false), start_addr(), end_addr(), at_pc(false),
39b9c1b51eSKate Stone       frame_line(false), plugin_name(), flavor_string(), arch(),
40b9c1b51eSKate Stone       some_location_specified(false), symbol_containing_addr() {
41e1cfbc79STodd Fiala   OptionParsingStarting(nullptr);
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
4426cac3afSEugene Zelenko CommandObjectDisassemble::CommandOptions::~CommandOptions() = default;
4530fdc8d8SChris Lattner 
4697206d57SZachary Turner Status CommandObjectDisassemble::CommandOptions::SetOptionValue(
47fe11483bSZachary Turner     uint32_t option_idx, llvm::StringRef option_arg,
48b9c1b51eSKate Stone     ExecutionContext *execution_context) {
4997206d57SZachary Turner   Status error;
5030fdc8d8SChris Lattner 
513bcdfc0eSGreg Clayton   const int short_option = m_getopt_table[option_idx].val;
5230fdc8d8SChris Lattner 
53b9c1b51eSKate Stone   switch (short_option) {
5430fdc8d8SChris Lattner   case 'm':
5530fdc8d8SChris Lattner     show_mixed = true;
5630fdc8d8SChris Lattner     break;
5730fdc8d8SChris Lattner 
58357132ebSGreg Clayton   case 'C':
59fe11483bSZachary Turner     if (option_arg.getAsInteger(0, num_lines_context))
60b9c1b51eSKate Stone       error.SetErrorStringWithFormat("invalid num context lines string: \"%s\"",
61fe11483bSZachary Turner                                      option_arg.str().c_str());
6237023b06SJim Ingham     break;
6337023b06SJim Ingham 
6430fdc8d8SChris Lattner   case 'c':
65fe11483bSZachary Turner     if (option_arg.getAsInteger(0, num_instructions))
66b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
67fe11483bSZachary Turner           "invalid num of instructions string: \"%s\"",
68fe11483bSZachary Turner           option_arg.str().c_str());
6930fdc8d8SChris Lattner     break;
7030fdc8d8SChris Lattner 
7130fdc8d8SChris Lattner   case 'b':
7230fdc8d8SChris Lattner     show_bytes = true;
7330fdc8d8SChris Lattner     break;
7430fdc8d8SChris Lattner 
75b9c1b51eSKate Stone   case 's': {
7647cbf4a0SPavel Labath     start_addr = OptionArgParser::ToAddress(execution_context, option_arg,
77e1cfbc79STodd Fiala                                             LLDB_INVALID_ADDRESS, &error);
78b9d5df58SGreg Clayton     if (start_addr != LLDB_INVALID_ADDRESS)
793555b5d7SJim Ingham       some_location_specified = true;
80b9c1b51eSKate Stone   } break;
81b9c1b51eSKate Stone   case 'e': {
8247cbf4a0SPavel Labath     end_addr = OptionArgParser::ToAddress(execution_context, option_arg,
83e1cfbc79STodd Fiala                                           LLDB_INVALID_ADDRESS, &error);
84b9d5df58SGreg Clayton     if (end_addr != LLDB_INVALID_ADDRESS)
853555b5d7SJim Ingham       some_location_specified = true;
86b9c1b51eSKate Stone   } break;
8726cac3afSEugene Zelenko 
8830fdc8d8SChris Lattner   case 'n':
8932e0a750SGreg Clayton     func_name.assign(option_arg);
903555b5d7SJim Ingham     some_location_specified = true;
9130fdc8d8SChris Lattner     break;
9230fdc8d8SChris Lattner 
9337023b06SJim Ingham   case 'p':
9432e0a750SGreg Clayton     at_pc = true;
953555b5d7SJim Ingham     some_location_specified = true;
9632e0a750SGreg Clayton     break;
9732e0a750SGreg Clayton 
9832e0a750SGreg Clayton   case 'l':
9932e0a750SGreg Clayton     frame_line = true;
10005097246SAdrian Prantl     // Disassemble the current source line kind of implies showing mixed source
10105097246SAdrian Prantl     // code context.
10232e0a750SGreg Clayton     show_mixed = true;
1033555b5d7SJim Ingham     some_location_specified = true;
10437023b06SJim Ingham     break;
10537023b06SJim Ingham 
1061080edbcSGreg Clayton   case 'P':
10732e0a750SGreg Clayton     plugin_name.assign(option_arg);
1081080edbcSGreg Clayton     break;
1091080edbcSGreg Clayton 
110b9c1b51eSKate Stone   case 'F': {
111b9c1b51eSKate Stone     TargetSP target_sp =
112b9c1b51eSKate Stone         execution_context ? execution_context->GetTargetSP() : TargetSP();
113b9c1b51eSKate Stone     if (target_sp && (target_sp->GetArchitecture().GetTriple().getArch() ==
114b9c1b51eSKate Stone                           llvm::Triple::x86 ||
115b9c1b51eSKate Stone                       target_sp->GetArchitecture().GetTriple().getArch() ==
116b9c1b51eSKate Stone                           llvm::Triple::x86_64)) {
1170f063ba6SJim Ingham       flavor_string.assign(option_arg);
118b9c1b51eSKate Stone     } else
119b9c1b51eSKate Stone       error.SetErrorStringWithFormat("Disassembler flavors are currently only "
120b9c1b51eSKate Stone                                      "supported for x86 and x86_64 targets.");
1210f063ba6SJim Ingham     break;
1220f063ba6SJim Ingham   }
12326cac3afSEugene Zelenko 
12430fdc8d8SChris Lattner   case 'r':
12530fdc8d8SChris Lattner     raw = true;
12630fdc8d8SChris Lattner     break;
12730fdc8d8SChris Lattner 
1288ceb8ba2SJohnny Chen   case 'f':
1291fb2e7dfSGreg Clayton     current_function = true;
1303555b5d7SJim Ingham     some_location_specified = true;
1318ceb8ba2SJohnny Chen     break;
1328ceb8ba2SJohnny Chen 
133801237a2SJason Molenda   case 'A':
134b9c1b51eSKate Stone     if (execution_context) {
135be73fd6bSTatyana Krasnukha       const auto &target_sp = execution_context->GetTargetSP();
136be73fd6bSTatyana Krasnukha       auto platform_ptr = target_sp ? target_sp->GetPlatform().get() : nullptr;
137be73fd6bSTatyana Krasnukha       arch = Platform::GetAugmentedArchSpec(platform_ptr, option_arg);
138e1cfbc79STodd Fiala     }
139357132ebSGreg Clayton     break;
140357132ebSGreg Clayton 
141b9c1b51eSKate Stone   case 'a': {
14247cbf4a0SPavel Labath     symbol_containing_addr = OptionArgParser::ToAddress(
143b9c1b51eSKate Stone         execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
144b9c1b51eSKate Stone     if (symbol_containing_addr != LLDB_INVALID_ADDRESS) {
145801237a2SJason Molenda       some_location_specified = true;
146801237a2SJason Molenda     }
147b9c1b51eSKate Stone   } break;
148801237a2SJason Molenda 
14930fdc8d8SChris Lattner   default:
15036162014SRaphael Isemann     llvm_unreachable("Unimplemented option");
15130fdc8d8SChris Lattner   }
15230fdc8d8SChris Lattner 
15330fdc8d8SChris Lattner   return error;
15430fdc8d8SChris Lattner }
15530fdc8d8SChris Lattner 
156b9c1b51eSKate Stone void CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
157b9c1b51eSKate Stone     ExecutionContext *execution_context) {
15830fdc8d8SChris Lattner   show_mixed = false;
15930fdc8d8SChris Lattner   show_bytes = false;
16030fdc8d8SChris Lattner   num_lines_context = 0;
16137023b06SJim Ingham   num_instructions = 0;
16232e0a750SGreg Clayton   func_name.clear();
1631fb2e7dfSGreg Clayton   current_function = false;
16432e0a750SGreg Clayton   at_pc = false;
16532e0a750SGreg Clayton   frame_line = false;
16632e0a750SGreg Clayton   start_addr = LLDB_INVALID_ADDRESS;
16732e0a750SGreg Clayton   end_addr = LLDB_INVALID_ADDRESS;
168801237a2SJason Molenda   symbol_containing_addr = LLDB_INVALID_ADDRESS;
169a68c1a21SSean Callanan   raw = false;
17032e0a750SGreg Clayton   plugin_name.clear();
1710f063ba6SJim Ingham 
172e1cfbc79STodd Fiala   Target *target =
173e1cfbc79STodd Fiala       execution_context ? execution_context->GetTargetPtr() : nullptr;
1740f063ba6SJim Ingham 
175b9c1b51eSKate Stone   // This is a hack till we get the ability to specify features based on
17605097246SAdrian Prantl   // architecture.  For now GetDisassemblyFlavor is really only valid for x86
17705097246SAdrian Prantl   // (and for the llvm assembler plugin, but I'm papering over that since that
17805097246SAdrian Prantl   // is the only disassembler plugin we have...
179b9c1b51eSKate Stone   if (target) {
180b9c1b51eSKate Stone     if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86 ||
181b9c1b51eSKate Stone         target->GetArchitecture().GetTriple().getArch() ==
182b9c1b51eSKate Stone             llvm::Triple::x86_64) {
1830f063ba6SJim Ingham       flavor_string.assign(target->GetDisassemblyFlavor());
184b9c1b51eSKate Stone     } else
1850f063ba6SJim Ingham       flavor_string.assign("default");
1860f063ba6SJim Ingham 
187b9c1b51eSKate Stone   } else
1880f063ba6SJim Ingham     flavor_string.assign("default");
1890f063ba6SJim Ingham 
19032e0a750SGreg Clayton   arch.Clear();
1913555b5d7SJim Ingham   some_location_specified = false;
1923555b5d7SJim Ingham }
1933555b5d7SJim Ingham 
19497206d57SZachary Turner Status CommandObjectDisassemble::CommandOptions::OptionParsingFinished(
195b9c1b51eSKate Stone     ExecutionContext *execution_context) {
1963555b5d7SJim Ingham   if (!some_location_specified)
1971fb2e7dfSGreg Clayton     current_function = true;
19897206d57SZachary Turner   return Status();
19930fdc8d8SChris Lattner }
20030fdc8d8SChris Lattner 
2011f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition>
202b9c1b51eSKate Stone CommandObjectDisassemble::CommandOptions::GetDefinitions() {
20370602439SZachary Turner   return llvm::makeArrayRef(g_disassemble_options);
20430fdc8d8SChris Lattner }
20530fdc8d8SChris Lattner 
20630fdc8d8SChris Lattner // CommandObjectDisassemble
20730fdc8d8SChris Lattner 
208b9c1b51eSKate Stone CommandObjectDisassemble::CommandObjectDisassemble(
209b9c1b51eSKate Stone     CommandInterpreter &interpreter)
210b9c1b51eSKate Stone     : CommandObjectParsed(
211b9c1b51eSKate Stone           interpreter, "disassemble",
212b9c1b51eSKate Stone           "Disassemble specified instructions in the current target.  "
2137428a18cSKate Stone           "Defaults to the current function for the current thread and "
2147428a18cSKate Stone           "stack frame.",
21504a4c091SRaphael Isemann           "disassemble [<cmd-options>]", eCommandRequiresTarget),
216b9c1b51eSKate Stone       m_options() {}
21730fdc8d8SChris Lattner 
21826cac3afSEugene Zelenko CommandObjectDisassemble::~CommandObjectDisassemble() = default;
21930fdc8d8SChris Lattner 
220b9c1b51eSKate Stone bool CommandObjectDisassemble::DoExecute(Args &command,
221b9c1b51eSKate Stone                                          CommandReturnObject &result) {
22204a4c091SRaphael Isemann   Target *target = &GetSelectedTarget();
22304a4c091SRaphael Isemann 
22432e0a750SGreg Clayton   if (!m_options.arch.IsValid())
22532e0a750SGreg Clayton     m_options.arch = target->GetArchitecture();
22630fdc8d8SChris Lattner 
227b9c1b51eSKate Stone   if (!m_options.arch.IsValid()) {
228b9c1b51eSKate Stone     result.AppendError(
229b9c1b51eSKate Stone         "use the --arch option or set the target architecture to disassemble");
23030fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
23130fdc8d8SChris Lattner     return false;
23230fdc8d8SChris Lattner   }
23330fdc8d8SChris Lattner 
2341080edbcSGreg Clayton   const char *plugin_name = m_options.GetPluginName();
2350f063ba6SJim Ingham   const char *flavor_string = m_options.GetFlavorString();
2360f063ba6SJim Ingham 
237b9c1b51eSKate Stone   DisassemblerSP disassembler =
238b9c1b51eSKate Stone       Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
23930fdc8d8SChris Lattner 
240b9c1b51eSKate Stone   if (!disassembler) {
241b9c1b51eSKate Stone     if (plugin_name) {
242b9c1b51eSKate Stone       result.AppendErrorWithFormat(
243b9c1b51eSKate Stone           "Unable to find Disassembler plug-in named '%s' that supports the "
244b9c1b51eSKate Stone           "'%s' architecture.\n",
245b9c1b51eSKate Stone           plugin_name, m_options.arch.GetArchitectureName());
246b9c1b51eSKate Stone     } else
247b9c1b51eSKate Stone       result.AppendErrorWithFormat(
248b9c1b51eSKate Stone           "Unable to find Disassembler plug-in for the '%s' architecture.\n",
24932e0a750SGreg Clayton           m_options.arch.GetArchitectureName());
25030fdc8d8SChris Lattner     result.SetStatus(eReturnStatusFailed);
25130fdc8d8SChris Lattner     return false;
252b9c1b51eSKate Stone   } else if (flavor_string != nullptr &&
253b9c1b51eSKate Stone              !disassembler->FlavorValidForArchSpec(m_options.arch,
254b9c1b51eSKate Stone                                                    flavor_string))
255b9c1b51eSKate Stone     result.AppendWarningWithFormat(
256b9c1b51eSKate Stone         "invalid disassembler flavor \"%s\", using default.\n", flavor_string);
25730fdc8d8SChris Lattner 
25830fdc8d8SChris Lattner   result.SetStatus(eReturnStatusSuccessFinishResult);
25930fdc8d8SChris Lattner 
26011eb9c64SZachary Turner   if (!command.empty()) {
261b9c1b51eSKate Stone     result.AppendErrorWithFormat(
262b9c1b51eSKate Stone         "\"disassemble\" arguments are specified as options.\n");
263e1cfbc79STodd Fiala     const int terminal_width =
264e1cfbc79STodd Fiala         GetCommandInterpreter().GetDebugger().GetTerminalWidth();
265e1cfbc79STodd Fiala     GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
266e1cfbc79STodd Fiala                                       terminal_width);
2678651121cSJim Ingham     result.SetStatus(eReturnStatusFailed);
2688651121cSJim Ingham     return false;
2698651121cSJim Ingham   }
2708651121cSJim Ingham 
271dda4f7b5SGreg Clayton   if (m_options.show_mixed && m_options.num_lines_context == 0)
2720b4c26b2SJason Molenda     m_options.num_lines_context = 2;
273dda4f7b5SGreg Clayton 
274b10d72f0SGreg Clayton   // Always show the PC in the disassembly
275b10d72f0SGreg Clayton   uint32_t options = Disassembler::eOptionMarkPCAddress;
2761da6f9d7SGreg Clayton 
277b9c1b51eSKate Stone   // Mark the source line for the current PC only if we are doing mixed source
278b9c1b51eSKate Stone   // and assembly
279b10d72f0SGreg Clayton   if (m_options.show_mixed)
280b10d72f0SGreg Clayton     options |= Disassembler::eOptionMarkPCSourceLine;
2811da6f9d7SGreg Clayton 
2821da6f9d7SGreg Clayton   if (m_options.show_bytes)
2831da6f9d7SGreg Clayton     options |= Disassembler::eOptionShowBytes;
2841da6f9d7SGreg Clayton 
2851da6f9d7SGreg Clayton   if (m_options.raw)
2861da6f9d7SGreg Clayton     options |= Disassembler::eOptionRawOuput;
28737023b06SJim Ingham 
288b9c1b51eSKate Stone   if (!m_options.func_name.empty()) {
28932e0a750SGreg Clayton     ConstString name(m_options.func_name.c_str());
290dda4f7b5SGreg Clayton 
291b9c1b51eSKate Stone     if (Disassembler::Disassemble(
29257179860SJonas Devlieghere             GetDebugger(), m_options.arch, plugin_name, flavor_string,
29357179860SJonas Devlieghere             m_exe_ctx, name,
29426cac3afSEugene Zelenko             nullptr, // Module *
2950b4c26b2SJason Molenda             m_options.num_instructions, m_options.show_mixed,
296b9c1b51eSKate Stone             m_options.show_mixed ? m_options.num_lines_context : 0, options,
297b9c1b51eSKate Stone             result.GetOutputStream())) {
298dda4f7b5SGreg Clayton       result.SetStatus(eReturnStatusSuccessFinishResult);
299b9c1b51eSKate Stone     } else {
300b9c1b51eSKate Stone       result.AppendErrorWithFormat("Unable to find symbol with name '%s'.\n",
301b9c1b51eSKate Stone                                    name.GetCString());
302dda4f7b5SGreg Clayton       result.SetStatus(eReturnStatusFailed);
303dda4f7b5SGreg Clayton     }
304b9c1b51eSKate Stone   } else {
3052f2c876eSJim Ingham     std::vector<AddressRange> ranges;
30632e0a750SGreg Clayton     AddressRange range;
307b57e4a1bSJason Molenda     StackFrame *frame = m_exe_ctx.GetFramePtr();
308b9c1b51eSKate Stone     if (m_options.frame_line) {
309b9c1b51eSKate Stone       if (frame == nullptr) {
310b9c1b51eSKate Stone         result.AppendError("Cannot disassemble around the current line without "
311b9c1b51eSKate Stone                            "a selected frame.\n");
3123555b5d7SJim Ingham         result.SetStatus(eReturnStatusFailed);
3133555b5d7SJim Ingham         return false;
3143555b5d7SJim Ingham       }
315b9c1b51eSKate Stone       LineEntry pc_line_entry(
316b9c1b51eSKate Stone           frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
317b9c1b51eSKate Stone       if (pc_line_entry.IsValid()) {
31832e0a750SGreg Clayton         range = pc_line_entry.range;
319b9c1b51eSKate Stone       } else {
320b9c1b51eSKate Stone         m_options.at_pc =
321b9c1b51eSKate Stone             true; // No line entry, so just disassemble around the current pc
32232e0a750SGreg Clayton         m_options.show_mixed = false;
32332e0a750SGreg Clayton       }
324b9c1b51eSKate Stone     } else if (m_options.current_function) {
325b9c1b51eSKate Stone       if (frame == nullptr) {
326b9c1b51eSKate Stone         result.AppendError("Cannot disassemble around the current function "
327b9c1b51eSKate Stone                            "without a selected frame.\n");
3283555b5d7SJim Ingham         result.SetStatus(eReturnStatusFailed);
3293555b5d7SJim Ingham         return false;
3303555b5d7SJim Ingham       }
331c14ee32dSGreg Clayton       Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
332b9c1b51eSKate Stone       if (symbol) {
333e7612134SGreg Clayton         range.GetBaseAddress() = symbol->GetAddress();
334e7612134SGreg Clayton         range.SetByteSize(symbol->GetByteSize());
335e7612134SGreg Clayton       }
3363555b5d7SJim Ingham     }
33737023b06SJim Ingham 
33805097246SAdrian Prantl     // Did the "m_options.frame_line" find a valid range already? If so skip
33905097246SAdrian Prantl     // the rest...
340b9c1b51eSKate Stone     if (range.GetByteSize() == 0) {
341b9c1b51eSKate Stone       if (m_options.at_pc) {
342b9c1b51eSKate Stone         if (frame == nullptr) {
343b9c1b51eSKate Stone           result.AppendError("Cannot disassemble around the current PC without "
344b9c1b51eSKate Stone                              "a selected frame.\n");
34537023b06SJim Ingham           result.SetStatus(eReturnStatusFailed);
34637023b06SJim Ingham           return false;
34737023b06SJim Ingham         }
348c14ee32dSGreg Clayton         range.GetBaseAddress() = frame->GetFrameCodeAddress();
349b9c1b51eSKate Stone         if (m_options.num_instructions == 0) {
350b9c1b51eSKate Stone           // Disassembling at the PC always disassembles some number of
351b9c1b51eSKate Stone           // instructions (not the whole function).
35237023b06SJim Ingham           m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
35337023b06SJim Ingham         }
3542f2c876eSJim Ingham         ranges.push_back(range);
355b9c1b51eSKate Stone       } else {
35632e0a750SGreg Clayton         range.GetBaseAddress().SetOffset(m_options.start_addr);
357b9c1b51eSKate Stone         if (range.GetBaseAddress().IsValid()) {
358b9c1b51eSKate Stone           if (m_options.end_addr != LLDB_INVALID_ADDRESS) {
359b9c1b51eSKate Stone             if (m_options.end_addr <= m_options.start_addr) {
360b9c1b51eSKate Stone               result.AppendErrorWithFormat(
361b9c1b51eSKate Stone                   "End address before start address.\n");
3628651121cSJim Ingham               result.SetStatus(eReturnStatusFailed);
3638651121cSJim Ingham               return false;
3648651121cSJim Ingham             }
36532e0a750SGreg Clayton             range.SetByteSize(m_options.end_addr - m_options.start_addr);
36632e0a750SGreg Clayton           }
3672f4693aaSJim Ingham           ranges.push_back(range);
368b9c1b51eSKate Stone         } else {
369b9c1b51eSKate Stone           if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS &&
370b9c1b51eSKate Stone               target) {
371b9c1b51eSKate Stone             if (!target->GetSectionLoadList().IsEmpty()) {
372801237a2SJason Molenda               bool failed = false;
373801237a2SJason Molenda               Address symbol_containing_address;
374b9c1b51eSKate Stone               if (target->GetSectionLoadList().ResolveLoadAddress(
375b9c1b51eSKate Stone                       m_options.symbol_containing_addr,
376b9c1b51eSKate Stone                       symbol_containing_address)) {
377801237a2SJason Molenda                 ModuleSP module_sp(symbol_containing_address.GetModule());
378801237a2SJason Molenda                 SymbolContext sc;
379b9c1b51eSKate Stone                 bool resolve_tail_call_address = true; // PC can be one past the
380b9c1b51eSKate Stone                                                        // address range of the
381b9c1b51eSKate Stone                                                        // function.
382b9c1b51eSKate Stone                 module_sp->ResolveSymbolContextForAddress(
383b9c1b51eSKate Stone                     symbol_containing_address, eSymbolContextEverything, sc,
38435729bb1SAshok Thirumurthi                     resolve_tail_call_address);
385b9c1b51eSKate Stone                 if (sc.function || sc.symbol) {
386b9c1b51eSKate Stone                   sc.GetAddressRange(eSymbolContextFunction |
387b9c1b51eSKate Stone                                          eSymbolContextSymbol,
388b9c1b51eSKate Stone                                      0, false, range);
389b9c1b51eSKate Stone                 } else {
390801237a2SJason Molenda                   failed = true;
391801237a2SJason Molenda                 }
392b9c1b51eSKate Stone               } else {
393801237a2SJason Molenda                 failed = true;
394801237a2SJason Molenda               }
395b9c1b51eSKate Stone               if (failed) {
396b9c1b51eSKate Stone                 result.AppendErrorWithFormat(
397b9c1b51eSKate Stone                     "Could not find function bounds for address 0x%" PRIx64
398b9c1b51eSKate Stone                     "\n",
399b9c1b51eSKate Stone                     m_options.symbol_containing_addr);
400801237a2SJason Molenda                 result.SetStatus(eReturnStatusFailed);
401801237a2SJason Molenda                 return false;
402801237a2SJason Molenda               }
4032f2c876eSJim Ingham               ranges.push_back(range);
404b9c1b51eSKate Stone             } else {
405b9c1b51eSKate Stone               for (lldb::ModuleSP module_sp : target->GetImages().Modules()) {
4062f2c876eSJim Ingham                 lldb::addr_t file_addr = m_options.symbol_containing_addr;
4072f2c876eSJim Ingham                 Address file_address;
408b9c1b51eSKate Stone                 if (module_sp->ResolveFileAddress(file_addr, file_address)) {
4092f2c876eSJim Ingham                   SymbolContext sc;
410b9c1b51eSKate Stone                   bool resolve_tail_call_address = true; // PC can be one past
411b9c1b51eSKate Stone                                                          // the address range of
412b9c1b51eSKate Stone                                                          // the function.
413b9c1b51eSKate Stone                   module_sp->ResolveSymbolContextForAddress(
414b9c1b51eSKate Stone                       file_address, eSymbolContextEverything, sc,
415b9c1b51eSKate Stone                       resolve_tail_call_address);
416b9c1b51eSKate Stone                   if (sc.function || sc.symbol) {
417b9c1b51eSKate Stone                     sc.GetAddressRange(eSymbolContextFunction |
418b9c1b51eSKate Stone                                            eSymbolContextSymbol,
419b9c1b51eSKate Stone                                        0, false, range);
4202f2c876eSJim Ingham                     ranges.push_back(range);
421801237a2SJason Molenda                   }
42237023b06SJim Ingham                 }
42337023b06SJim Ingham               }
4242f2c876eSJim Ingham             }
4252f2c876eSJim Ingham           }
4262f2c876eSJim Ingham         }
4272f2c876eSJim Ingham       }
428b9c1b51eSKate Stone     } else
4292f2c876eSJim Ingham       ranges.push_back(range);
4302f2c876eSJim Ingham 
431b9c1b51eSKate Stone     if (m_options.num_instructions != 0) {
432b9c1b51eSKate Stone       if (ranges.empty()) {
43337023b06SJim Ingham         // The default action is to disassemble the current frame function.
434b9c1b51eSKate Stone         if (frame) {
435b9c1b51eSKate Stone           SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
436b9c1b51eSKate Stone                                                    eSymbolContextSymbol));
43737023b06SJim Ingham           if (sc.function)
438b9c1b51eSKate Stone             range.GetBaseAddress() =
439b9c1b51eSKate Stone                 sc.function->GetAddressRange().GetBaseAddress();
440e7612134SGreg Clayton           else if (sc.symbol && sc.symbol->ValueIsAddress())
441e7612134SGreg Clayton             range.GetBaseAddress() = sc.symbol->GetAddress();
44237023b06SJim Ingham           else
443c14ee32dSGreg Clayton             range.GetBaseAddress() = frame->GetFrameCodeAddress();
44437023b06SJim Ingham         }
44537023b06SJim Ingham 
446b9c1b51eSKate Stone         if (!range.GetBaseAddress().IsValid()) {
44737023b06SJim Ingham           result.AppendError("invalid frame");
44837023b06SJim Ingham           result.SetStatus(eReturnStatusFailed);
44937023b06SJim Ingham           return false;
45037023b06SJim Ingham         }
45137023b06SJim Ingham       }
45237023b06SJim Ingham 
4532f2c876eSJim Ingham       bool print_sc_header = ranges.size() > 1;
454b9c1b51eSKate Stone       for (AddressRange cur_range : ranges) {
455b9c1b51eSKate Stone         if (Disassembler::Disassemble(
45657179860SJonas Devlieghere                 GetDebugger(), m_options.arch, plugin_name, flavor_string,
45757179860SJonas Devlieghere                 m_exe_ctx, cur_range.GetBaseAddress(),
4580b4c26b2SJason Molenda                 m_options.num_instructions, m_options.show_mixed,
459b9c1b51eSKate Stone                 m_options.show_mixed ? m_options.num_lines_context : 0, options,
460b9c1b51eSKate Stone                 result.GetOutputStream())) {
46137023b06SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishResult);
462b9c1b51eSKate Stone         } else {
4632f2c876eSJim Ingham           if (m_options.start_addr != LLDB_INVALID_ADDRESS)
464b9c1b51eSKate Stone             result.AppendErrorWithFormat(
465b9c1b51eSKate Stone                 "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
466b9c1b51eSKate Stone                 m_options.start_addr);
4672f2c876eSJim Ingham           else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
468b9c1b51eSKate Stone             result.AppendErrorWithFormat(
469b9c1b51eSKate Stone                 "Failed to disassemble memory in function at 0x%8.8" PRIx64
470b9c1b51eSKate Stone                 ".\n",
471b9c1b51eSKate Stone                 m_options.symbol_containing_addr);
47237023b06SJim Ingham           result.SetStatus(eReturnStatusFailed);
47337023b06SJim Ingham         }
47437023b06SJim Ingham       }
4752f2c876eSJim Ingham       if (print_sc_header)
4762f2c876eSJim Ingham         result.AppendMessage("\n");
477b9c1b51eSKate Stone     } else {
478b9c1b51eSKate Stone       if (ranges.empty()) {
4798ceb8ba2SJohnny Chen         // The default action is to disassemble the current frame function.
480b9c1b51eSKate Stone         if (frame) {
481b9c1b51eSKate Stone           SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction |
482b9c1b51eSKate Stone                                                    eSymbolContextSymbol));
48330fdc8d8SChris Lattner           if (sc.function)
484dda4f7b5SGreg Clayton             range = sc.function->GetAddressRange();
485b9c1b51eSKate Stone           else if (sc.symbol && sc.symbol->ValueIsAddress()) {
486e7612134SGreg Clayton             range.GetBaseAddress() = sc.symbol->GetAddress();
487e7612134SGreg Clayton             range.SetByteSize(sc.symbol->GetByteSize());
488b9c1b51eSKate Stone           } else
489c14ee32dSGreg Clayton             range.GetBaseAddress() = frame->GetFrameCodeAddress();
490b9c1b51eSKate Stone         } else {
49130fdc8d8SChris Lattner           result.AppendError("invalid frame");
49230fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
49330fdc8d8SChris Lattner           return false;
49430fdc8d8SChris Lattner         }
4952f2c876eSJim Ingham         ranges.push_back(range);
49630fdc8d8SChris Lattner       }
4972f2c876eSJim Ingham 
4982f2c876eSJim Ingham       bool print_sc_header = ranges.size() > 1;
499b9c1b51eSKate Stone       for (AddressRange cur_range : ranges) {
5002f2c876eSJim Ingham         if (cur_range.GetByteSize() == 0)
5012f2c876eSJim Ingham           cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
50230fdc8d8SChris Lattner 
503b9c1b51eSKate Stone         if (Disassembler::Disassemble(
50457179860SJonas Devlieghere                 GetDebugger(), m_options.arch, plugin_name, flavor_string,
50557179860SJonas Devlieghere                 m_exe_ctx, cur_range, m_options.num_instructions,
5060b4c26b2SJason Molenda                 m_options.show_mixed,
507b9c1b51eSKate Stone                 m_options.show_mixed ? m_options.num_lines_context : 0, options,
508b9c1b51eSKate Stone                 result.GetOutputStream())) {
509dda4f7b5SGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishResult);
510b9c1b51eSKate Stone         } else {
511b9c1b51eSKate Stone           result.AppendErrorWithFormat(
512b9c1b51eSKate Stone               "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n",
513*05229752SPavel Labath               cur_range.GetBaseAddress().GetLoadAddress(target));
51430fdc8d8SChris Lattner           result.SetStatus(eReturnStatusFailed);
51530fdc8d8SChris Lattner         }
5162f2c876eSJim Ingham         if (print_sc_header)
5172f2c876eSJim Ingham           result.AppendMessage("\n");
5182f2c876eSJim Ingham       }
51930fdc8d8SChris Lattner     }
52037023b06SJim Ingham   }
52130fdc8d8SChris Lattner 
52230fdc8d8SChris Lattner   return result.Succeeded();
52330fdc8d8SChris Lattner }
524