130fdc8d8SChris Lattner //===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "CommandObjectDisassemble.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1630fdc8d8SChris Lattner #include "lldb/Core/AddressRange.h"
1740af72e1SJim Ingham #include "lldb/Interpreter/Args.h"
1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandCompletions.h"
1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
2130fdc8d8SChris Lattner #include "lldb/Core/Disassembler.h"
2240af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
2330fdc8d8SChris Lattner #include "lldb/Core/SourceManager.h"
2430fdc8d8SChris Lattner #include "lldb/Target/StackFrame.h"
2530fdc8d8SChris Lattner #include "lldb/Symbol/Symbol.h"
2630fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2730fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner #define DEFAULT_DISASM_BYTE_SIZE 32
3030fdc8d8SChris Lattner 
3130fdc8d8SChris Lattner using namespace lldb;
3230fdc8d8SChris Lattner using namespace lldb_private;
3330fdc8d8SChris Lattner 
3430fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::CommandOptions () :
3530fdc8d8SChris Lattner     Options(),
3630fdc8d8SChris Lattner     m_func_name(),
378651121cSJim Ingham     m_start_addr(),
388651121cSJim Ingham     m_end_addr ()
3930fdc8d8SChris Lattner {
4030fdc8d8SChris Lattner     ResetOptionValues();
4130fdc8d8SChris Lattner }
4230fdc8d8SChris Lattner 
4330fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::~CommandOptions ()
4430fdc8d8SChris Lattner {
4530fdc8d8SChris Lattner }
4630fdc8d8SChris Lattner 
4730fdc8d8SChris Lattner Error
4830fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
4930fdc8d8SChris Lattner {
5030fdc8d8SChris Lattner     Error error;
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner     char short_option = (char) m_getopt_table[option_idx].val;
5330fdc8d8SChris Lattner 
5430fdc8d8SChris Lattner     switch (short_option)
5530fdc8d8SChris Lattner     {
5630fdc8d8SChris Lattner     case 'm':
5730fdc8d8SChris Lattner         show_mixed = true;
5830fdc8d8SChris Lattner         break;
5930fdc8d8SChris Lattner 
6030fdc8d8SChris Lattner     case 'c':
6130fdc8d8SChris Lattner         num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
6230fdc8d8SChris Lattner         break;
6330fdc8d8SChris Lattner 
6430fdc8d8SChris Lattner     case 'b':
6530fdc8d8SChris Lattner         show_bytes = true;
6630fdc8d8SChris Lattner         break;
6730fdc8d8SChris Lattner 
688651121cSJim Ingham     case 's':
698651121cSJim Ingham         m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
708651121cSJim Ingham         if (m_start_addr == LLDB_INVALID_ADDRESS)
718651121cSJim Ingham             m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
7230fdc8d8SChris Lattner 
738651121cSJim Ingham         if (m_start_addr == LLDB_INVALID_ADDRESS)
748651121cSJim Ingham             error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", optarg);
758651121cSJim Ingham         break;
768651121cSJim Ingham     case 'e':
778651121cSJim Ingham         m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
788651121cSJim Ingham         if (m_end_addr == LLDB_INVALID_ADDRESS)
798651121cSJim Ingham             m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
808651121cSJim Ingham 
818651121cSJim Ingham         if (m_end_addr == LLDB_INVALID_ADDRESS)
828651121cSJim Ingham             error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", optarg);
8330fdc8d8SChris Lattner         break;
8430fdc8d8SChris Lattner 
8530fdc8d8SChris Lattner     case 'n':
8630fdc8d8SChris Lattner         m_func_name = option_arg;
8730fdc8d8SChris Lattner         break;
8830fdc8d8SChris Lattner 
8930fdc8d8SChris Lattner     case 'r':
9030fdc8d8SChris Lattner         raw = true;
9130fdc8d8SChris Lattner         break;
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner     default:
9430fdc8d8SChris Lattner         error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
9530fdc8d8SChris Lattner         break;
9630fdc8d8SChris Lattner     }
9730fdc8d8SChris Lattner 
9830fdc8d8SChris Lattner     return error;
9930fdc8d8SChris Lattner }
10030fdc8d8SChris Lattner 
10130fdc8d8SChris Lattner void
10230fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
10330fdc8d8SChris Lattner {
10430fdc8d8SChris Lattner     Options::ResetOptionValues();
10530fdc8d8SChris Lattner     show_mixed = false;
10630fdc8d8SChris Lattner     show_bytes = false;
10730fdc8d8SChris Lattner     num_lines_context = 0;
10830fdc8d8SChris Lattner     m_func_name.clear();
1098651121cSJim Ingham     m_start_addr = LLDB_INVALID_ADDRESS;
1108651121cSJim Ingham     m_end_addr = LLDB_INVALID_ADDRESS;
111a68c1a21SSean Callanan     raw = false;
11230fdc8d8SChris Lattner }
11330fdc8d8SChris Lattner 
11430fdc8d8SChris Lattner const lldb::OptionDefinition*
11530fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::GetDefinitions ()
11630fdc8d8SChris Lattner {
11730fdc8d8SChris Lattner     return g_option_table;
11830fdc8d8SChris Lattner }
11930fdc8d8SChris Lattner 
12030fdc8d8SChris Lattner lldb::OptionDefinition
12130fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::g_option_table[] =
12230fdc8d8SChris Lattner {
123deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "bytes",    'b', no_argument,       NULL, 0, eArgTypeNone,             "Show opcode bytes when disassembling."},
124deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "context",  'c', required_argument, NULL, 0, eArgTypeNumLines,    "Number of context lines of source to show."},
125deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "mixed",    'm', no_argument,       NULL, 0, eArgTypeNone,             "Enable mixed source and assembly display."},
126deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "raw",      'r', no_argument,       NULL, 0, eArgTypeNone,             "Print raw disassembly with no symbol information."},
12730fdc8d8SChris Lattner 
128*405fe67fSCaroline Tice { LLDB_OPT_SET_1, true, "start-address",  's', required_argument, NULL, 0, eArgTypeStartAddress,      "Address at which to start disassembling."},
129*405fe67fSCaroline Tice { LLDB_OPT_SET_1, false, "end-address",  'e', required_argument, NULL, 0, eArgTypeEndAddress,      "Address at which to end disassembling."},
13030fdc8d8SChris Lattner 
131deaab222SCaroline Tice { LLDB_OPT_SET_2, true, "name",     'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,             "Disassemble entire contents of the given function name."},
1328651121cSJim Ingham 
1338d88020eSCaroline Tice { LLDB_OPT_SET_3, false, "current-frame",     'f', no_argument, NULL, 0, eArgTypeNone,             "Disassemble entire contents of the current frame's function."},
13430fdc8d8SChris Lattner 
135deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
13630fdc8d8SChris Lattner };
13730fdc8d8SChris Lattner 
13830fdc8d8SChris Lattner 
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner //-------------------------------------------------------------------------
14130fdc8d8SChris Lattner // CommandObjectDisassemble
14230fdc8d8SChris Lattner //-------------------------------------------------------------------------
14330fdc8d8SChris Lattner 
144a7015092SGreg Clayton CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) :
145a7015092SGreg Clayton     CommandObject (interpreter,
146a7015092SGreg Clayton                    "disassemble",
1473f4c09c1SCaroline Tice                    "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.",
1488651121cSJim Ingham                    "disassemble [<cmd-options>]")
14930fdc8d8SChris Lattner {
15030fdc8d8SChris Lattner }
15130fdc8d8SChris Lattner 
15230fdc8d8SChris Lattner CommandObjectDisassemble::~CommandObjectDisassemble()
15330fdc8d8SChris Lattner {
15430fdc8d8SChris Lattner }
15530fdc8d8SChris Lattner 
15630fdc8d8SChris Lattner bool
15730fdc8d8SChris Lattner CommandObjectDisassemble::Execute
15830fdc8d8SChris Lattner (
15930fdc8d8SChris Lattner     Args& command,
16030fdc8d8SChris Lattner     CommandReturnObject &result
16130fdc8d8SChris Lattner )
16230fdc8d8SChris Lattner {
163a7015092SGreg Clayton     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
16430fdc8d8SChris Lattner     if (target == NULL)
16530fdc8d8SChris Lattner     {
16630fdc8d8SChris Lattner         result.AppendError ("invalid target, set executable file using 'file' command");
16730fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
16830fdc8d8SChris Lattner         return false;
16930fdc8d8SChris Lattner     }
17030fdc8d8SChris Lattner 
17130fdc8d8SChris Lattner     ArchSpec arch(target->GetArchitecture());
17230fdc8d8SChris Lattner     if (!arch.IsValid())
17330fdc8d8SChris Lattner     {
17430fdc8d8SChris Lattner         result.AppendError ("target needs valid architecure in order to be able to disassemble");
17530fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
17630fdc8d8SChris Lattner         return false;
17730fdc8d8SChris Lattner     }
17830fdc8d8SChris Lattner 
17930fdc8d8SChris Lattner     Disassembler *disassembler = Disassembler::FindPlugin(arch);
18030fdc8d8SChris Lattner 
18130fdc8d8SChris Lattner     if (disassembler == NULL)
18230fdc8d8SChris Lattner     {
18330fdc8d8SChris Lattner         result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString());
18430fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
18530fdc8d8SChris Lattner         return false;
18630fdc8d8SChris Lattner     }
18730fdc8d8SChris Lattner 
18830fdc8d8SChris Lattner     result.SetStatus (eReturnStatusSuccessFinishResult);
18930fdc8d8SChris Lattner 
190dda4f7b5SGreg Clayton     if (command.GetArgumentCount() != 0)
19130fdc8d8SChris Lattner     {
192a7015092SGreg Clayton         result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
193a7015092SGreg Clayton         GetOptions()->GenerateOptionUsage (m_interpreter,
194a7015092SGreg Clayton                                            result.GetErrorStream(),
195a7015092SGreg Clayton                                            this);
196a7015092SGreg Clayton 
1978651121cSJim Ingham         result.SetStatus (eReturnStatusFailed);
1988651121cSJim Ingham         return false;
1998651121cSJim Ingham     }
200a7015092SGreg Clayton     ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
2018651121cSJim Ingham 
202dda4f7b5SGreg Clayton     if (m_options.show_mixed && m_options.num_lines_context == 0)
2036dbd3983SGreg Clayton         m_options.num_lines_context = 1;
204dda4f7b5SGreg Clayton 
205dda4f7b5SGreg Clayton     if (!m_options.m_func_name.empty())
206dda4f7b5SGreg Clayton     {
207dda4f7b5SGreg Clayton         ConstString name(m_options.m_func_name.c_str());
208dda4f7b5SGreg Clayton 
209a7015092SGreg Clayton         if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
210dda4f7b5SGreg Clayton                                        arch,
211dda4f7b5SGreg Clayton                                        exe_ctx,
212dda4f7b5SGreg Clayton                                        name,
213dda4f7b5SGreg Clayton                                        NULL,    // Module *
214dda4f7b5SGreg Clayton                                        m_options.show_mixed ? m_options.num_lines_context : 0,
215dda4f7b5SGreg Clayton                                        m_options.show_bytes,
216dda4f7b5SGreg Clayton                                        result.GetOutputStream()))
217dda4f7b5SGreg Clayton         {
218dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusSuccessFinishResult);
219dda4f7b5SGreg Clayton         }
220dda4f7b5SGreg Clayton         else
221dda4f7b5SGreg Clayton         {
222dda4f7b5SGreg Clayton             result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
223dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusFailed);
224dda4f7b5SGreg Clayton         }
225dda4f7b5SGreg Clayton     }
226dda4f7b5SGreg Clayton     else
227dda4f7b5SGreg Clayton     {
228dda4f7b5SGreg Clayton         AddressRange range;
2298651121cSJim Ingham         if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
2308651121cSJim Ingham         {
231dda4f7b5SGreg Clayton             range.GetBaseAddress().SetOffset (m_options.m_start_addr);
2328651121cSJim Ingham             if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
2338651121cSJim Ingham             {
234dda4f7b5SGreg Clayton                 if (m_options.m_end_addr < m_options.m_start_addr)
2358651121cSJim Ingham                 {
2368651121cSJim Ingham                     result.AppendErrorWithFormat ("End address before start address.\n");
2378651121cSJim Ingham                     result.SetStatus (eReturnStatusFailed);
2388651121cSJim Ingham                     return false;
2398651121cSJim Ingham                 }
240dda4f7b5SGreg Clayton                 range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr);
2418651121cSJim Ingham             }
2428651121cSJim Ingham             else
243dda4f7b5SGreg Clayton                 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
2448651121cSJim Ingham         }
2458651121cSJim Ingham         else
24630fdc8d8SChris Lattner         {
24730fdc8d8SChris Lattner             if (exe_ctx.frame)
24830fdc8d8SChris Lattner             {
24930fdc8d8SChris Lattner                 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
25030fdc8d8SChris Lattner                 if (sc.function)
251dda4f7b5SGreg Clayton                     range = sc.function->GetAddressRange();
25230fdc8d8SChris Lattner                 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
253dda4f7b5SGreg Clayton                     range = *sc.symbol->GetAddressRangePtr();
25430fdc8d8SChris Lattner                 else
2559da7bd07SGreg Clayton                     range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
25630fdc8d8SChris Lattner             }
25730fdc8d8SChris Lattner             else
25830fdc8d8SChris Lattner             {
25930fdc8d8SChris Lattner                 result.AppendError ("invalid frame");
26030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
26130fdc8d8SChris Lattner                 return false;
26230fdc8d8SChris Lattner             }
26330fdc8d8SChris Lattner         }
264dda4f7b5SGreg Clayton         if (range.GetByteSize() == 0)
265dda4f7b5SGreg Clayton             range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
26630fdc8d8SChris Lattner 
267a7015092SGreg Clayton         if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
268dda4f7b5SGreg Clayton                                        arch,
269dda4f7b5SGreg Clayton                                        exe_ctx,
270dda4f7b5SGreg Clayton                                        range,
271dda4f7b5SGreg Clayton                                        m_options.show_mixed ? m_options.num_lines_context : 0,
272dda4f7b5SGreg Clayton                                        m_options.show_bytes,
273dda4f7b5SGreg Clayton                                        result.GetOutputStream()))
27430fdc8d8SChris Lattner         {
275dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusSuccessFinishResult);
27630fdc8d8SChris Lattner         }
27730fdc8d8SChris Lattner         else
27830fdc8d8SChris Lattner         {
279dda4f7b5SGreg Clayton             result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
28030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
28130fdc8d8SChris Lattner         }
28230fdc8d8SChris Lattner     }
28330fdc8d8SChris Lattner 
28430fdc8d8SChris Lattner     return result.Succeeded();
28530fdc8d8SChris Lattner }
286