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 
938ceb8ba2SJohnny Chen     case 'f':
948ceb8ba2SJohnny Chen         // The default action is to disassemble the function for the current frame.
958ceb8ba2SJohnny Chen         // There's no need to set any flag.
968ceb8ba2SJohnny Chen         break;
978ceb8ba2SJohnny Chen 
9830fdc8d8SChris Lattner     default:
9930fdc8d8SChris Lattner         error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
10030fdc8d8SChris Lattner         break;
10130fdc8d8SChris Lattner     }
10230fdc8d8SChris Lattner 
10330fdc8d8SChris Lattner     return error;
10430fdc8d8SChris Lattner }
10530fdc8d8SChris Lattner 
10630fdc8d8SChris Lattner void
10730fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
10830fdc8d8SChris Lattner {
10930fdc8d8SChris Lattner     Options::ResetOptionValues();
11030fdc8d8SChris Lattner     show_mixed = false;
11130fdc8d8SChris Lattner     show_bytes = false;
11230fdc8d8SChris Lattner     num_lines_context = 0;
11330fdc8d8SChris Lattner     m_func_name.clear();
1148651121cSJim Ingham     m_start_addr = LLDB_INVALID_ADDRESS;
1158651121cSJim Ingham     m_end_addr = LLDB_INVALID_ADDRESS;
116a68c1a21SSean Callanan     raw = false;
11730fdc8d8SChris Lattner }
11830fdc8d8SChris Lattner 
11930fdc8d8SChris Lattner const lldb::OptionDefinition*
12030fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::GetDefinitions ()
12130fdc8d8SChris Lattner {
12230fdc8d8SChris Lattner     return g_option_table;
12330fdc8d8SChris Lattner }
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner lldb::OptionDefinition
12630fdc8d8SChris Lattner CommandObjectDisassemble::CommandOptions::g_option_table[] =
12730fdc8d8SChris Lattner {
128deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "bytes",    'b', no_argument,       NULL, 0, eArgTypeNone,             "Show opcode bytes when disassembling."},
129deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "context",  'c', required_argument, NULL, 0, eArgTypeNumLines,    "Number of context lines of source to show."},
130deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "mixed",    'm', no_argument,       NULL, 0, eArgTypeNone,             "Enable mixed source and assembly display."},
131deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "raw",      'r', no_argument,       NULL, 0, eArgTypeNone,             "Print raw disassembly with no symbol information."},
13230fdc8d8SChris Lattner 
133405fe67fSCaroline Tice { LLDB_OPT_SET_1, true, "start-address",  's', required_argument, NULL, 0, eArgTypeStartAddress,      "Address at which to start disassembling."},
134405fe67fSCaroline Tice { LLDB_OPT_SET_1, false, "end-address",  'e', required_argument, NULL, 0, eArgTypeEndAddress,      "Address at which to end disassembling."},
13530fdc8d8SChris Lattner 
136deaab222SCaroline Tice { LLDB_OPT_SET_2, true, "name",     'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,             "Disassemble entire contents of the given function name."},
1378651121cSJim Ingham 
1388ceb8ba2SJohnny Chen { LLDB_OPT_SET_3, true, "current-frame", 'f',  no_argument, NULL, 0, eArgTypeNone,             "Disassemble entire contents of the current frame's function."},
13930fdc8d8SChris Lattner 
140deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
14130fdc8d8SChris Lattner };
14230fdc8d8SChris Lattner 
14330fdc8d8SChris Lattner 
14430fdc8d8SChris Lattner 
14530fdc8d8SChris Lattner //-------------------------------------------------------------------------
14630fdc8d8SChris Lattner // CommandObjectDisassemble
14730fdc8d8SChris Lattner //-------------------------------------------------------------------------
14830fdc8d8SChris Lattner 
149a7015092SGreg Clayton CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) :
150a7015092SGreg Clayton     CommandObject (interpreter,
151a7015092SGreg Clayton                    "disassemble",
1523f4c09c1SCaroline Tice                    "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.",
1538651121cSJim Ingham                    "disassemble [<cmd-options>]")
15430fdc8d8SChris Lattner {
15530fdc8d8SChris Lattner }
15630fdc8d8SChris Lattner 
15730fdc8d8SChris Lattner CommandObjectDisassemble::~CommandObjectDisassemble()
15830fdc8d8SChris Lattner {
15930fdc8d8SChris Lattner }
16030fdc8d8SChris Lattner 
16130fdc8d8SChris Lattner bool
16230fdc8d8SChris Lattner CommandObjectDisassemble::Execute
16330fdc8d8SChris Lattner (
16430fdc8d8SChris Lattner     Args& command,
16530fdc8d8SChris Lattner     CommandReturnObject &result
16630fdc8d8SChris Lattner )
16730fdc8d8SChris Lattner {
168a7015092SGreg Clayton     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
16930fdc8d8SChris Lattner     if (target == NULL)
17030fdc8d8SChris Lattner     {
17130fdc8d8SChris Lattner         result.AppendError ("invalid target, set executable file using 'file' command");
17230fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
17330fdc8d8SChris Lattner         return false;
17430fdc8d8SChris Lattner     }
17530fdc8d8SChris Lattner 
17630fdc8d8SChris Lattner     ArchSpec arch(target->GetArchitecture());
17730fdc8d8SChris Lattner     if (!arch.IsValid())
17830fdc8d8SChris Lattner     {
17930fdc8d8SChris Lattner         result.AppendError ("target needs valid architecure in order to be able to disassemble");
18030fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
18130fdc8d8SChris Lattner         return false;
18230fdc8d8SChris Lattner     }
18330fdc8d8SChris Lattner 
18430fdc8d8SChris Lattner     Disassembler *disassembler = Disassembler::FindPlugin(arch);
18530fdc8d8SChris Lattner 
18630fdc8d8SChris Lattner     if (disassembler == NULL)
18730fdc8d8SChris Lattner     {
18830fdc8d8SChris Lattner         result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString());
18930fdc8d8SChris Lattner         result.SetStatus (eReturnStatusFailed);
19030fdc8d8SChris Lattner         return false;
19130fdc8d8SChris Lattner     }
19230fdc8d8SChris Lattner 
19330fdc8d8SChris Lattner     result.SetStatus (eReturnStatusSuccessFinishResult);
19430fdc8d8SChris Lattner 
195dda4f7b5SGreg Clayton     if (command.GetArgumentCount() != 0)
19630fdc8d8SChris Lattner     {
197a7015092SGreg Clayton         result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
198a7015092SGreg Clayton         GetOptions()->GenerateOptionUsage (m_interpreter,
199a7015092SGreg Clayton                                            result.GetErrorStream(),
200a7015092SGreg Clayton                                            this);
201a7015092SGreg Clayton 
2028651121cSJim Ingham         result.SetStatus (eReturnStatusFailed);
2038651121cSJim Ingham         return false;
2048651121cSJim Ingham     }
205a7015092SGreg Clayton     ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
2068651121cSJim Ingham 
207dda4f7b5SGreg Clayton     if (m_options.show_mixed && m_options.num_lines_context == 0)
2086dbd3983SGreg Clayton         m_options.num_lines_context = 1;
209dda4f7b5SGreg Clayton 
210dda4f7b5SGreg Clayton     if (!m_options.m_func_name.empty())
211dda4f7b5SGreg Clayton     {
212dda4f7b5SGreg Clayton         ConstString name(m_options.m_func_name.c_str());
213dda4f7b5SGreg Clayton 
214a7015092SGreg Clayton         if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
215dda4f7b5SGreg Clayton                                        arch,
216dda4f7b5SGreg Clayton                                        exe_ctx,
217dda4f7b5SGreg Clayton                                        name,
218dda4f7b5SGreg Clayton                                        NULL,    // Module *
219dda4f7b5SGreg Clayton                                        m_options.show_mixed ? m_options.num_lines_context : 0,
220dda4f7b5SGreg Clayton                                        m_options.show_bytes,
221dda4f7b5SGreg Clayton                                        result.GetOutputStream()))
222dda4f7b5SGreg Clayton         {
223dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusSuccessFinishResult);
224dda4f7b5SGreg Clayton         }
225dda4f7b5SGreg Clayton         else
226dda4f7b5SGreg Clayton         {
227dda4f7b5SGreg Clayton             result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
228dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusFailed);
229dda4f7b5SGreg Clayton         }
230dda4f7b5SGreg Clayton     }
231dda4f7b5SGreg Clayton     else
232dda4f7b5SGreg Clayton     {
233dda4f7b5SGreg Clayton         AddressRange range;
2348651121cSJim Ingham         if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
2358651121cSJim Ingham         {
236dda4f7b5SGreg Clayton             range.GetBaseAddress().SetOffset (m_options.m_start_addr);
2378651121cSJim Ingham             if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
2388651121cSJim Ingham             {
239dda4f7b5SGreg Clayton                 if (m_options.m_end_addr < m_options.m_start_addr)
2408651121cSJim Ingham                 {
2418651121cSJim Ingham                     result.AppendErrorWithFormat ("End address before start address.\n");
2428651121cSJim Ingham                     result.SetStatus (eReturnStatusFailed);
2438651121cSJim Ingham                     return false;
2448651121cSJim Ingham                 }
245dda4f7b5SGreg Clayton                 range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr);
2468651121cSJim Ingham             }
2478651121cSJim Ingham             else
248dda4f7b5SGreg Clayton                 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
2498651121cSJim Ingham         }
2508651121cSJim Ingham         else
25130fdc8d8SChris Lattner         {
2528ceb8ba2SJohnny Chen             // The default action is to disassemble the current frame function.
25330fdc8d8SChris Lattner             if (exe_ctx.frame)
25430fdc8d8SChris Lattner             {
255*dae97b4aSJason Molenda                 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
25630fdc8d8SChris Lattner                 if (sc.function)
257dda4f7b5SGreg Clayton                     range = sc.function->GetAddressRange();
25830fdc8d8SChris Lattner                 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
259dda4f7b5SGreg Clayton                     range = *sc.symbol->GetAddressRangePtr();
26030fdc8d8SChris Lattner                 else
2619da7bd07SGreg Clayton                     range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
26230fdc8d8SChris Lattner             }
26330fdc8d8SChris Lattner             else
26430fdc8d8SChris Lattner             {
26530fdc8d8SChris Lattner                 result.AppendError ("invalid frame");
26630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
26730fdc8d8SChris Lattner                 return false;
26830fdc8d8SChris Lattner             }
26930fdc8d8SChris Lattner         }
270dda4f7b5SGreg Clayton         if (range.GetByteSize() == 0)
271dda4f7b5SGreg Clayton             range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
27230fdc8d8SChris Lattner 
273a7015092SGreg Clayton         if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
274dda4f7b5SGreg Clayton                                        arch,
275dda4f7b5SGreg Clayton                                        exe_ctx,
276dda4f7b5SGreg Clayton                                        range,
277dda4f7b5SGreg Clayton                                        m_options.show_mixed ? m_options.num_lines_context : 0,
278dda4f7b5SGreg Clayton                                        m_options.show_bytes,
279dda4f7b5SGreg Clayton                                        result.GetOutputStream()))
28030fdc8d8SChris Lattner         {
281dda4f7b5SGreg Clayton             result.SetStatus (eReturnStatusSuccessFinishResult);
28230fdc8d8SChris Lattner         }
28330fdc8d8SChris Lattner         else
28430fdc8d8SChris Lattner         {
285dda4f7b5SGreg Clayton             result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
28630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
28730fdc8d8SChris Lattner         }
28830fdc8d8SChris Lattner     }
28930fdc8d8SChris Lattner 
29030fdc8d8SChris Lattner     return result.Succeeded();
29130fdc8d8SChris Lattner }
292