blob: a4dd5ac380591f8d216308b612daf5bdb1722399 [file] [log] [blame]
Chris Lattner24943d22010-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
10#include "CommandObjectDisassemble.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/AddressRange.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000017#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandCompletions.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
21#include "lldb/Core/Disassembler.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000022#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Core/SourceManager.h"
24#include "lldb/Target/StackFrame.h"
25#include "lldb/Symbol/Symbol.h"
26#include "lldb/Target/Process.h"
27#include "lldb/Target/Target.h"
28
29#define DEFAULT_DISASM_BYTE_SIZE 32
30
31using namespace lldb;
32using namespace lldb_private;
33
34CommandObjectDisassemble::CommandOptions::CommandOptions () :
35 Options(),
36 m_func_name(),
Jim Ingham34e9a982010-06-15 18:47:14 +000037 m_start_addr(),
38 m_end_addr ()
Chris Lattner24943d22010-06-08 16:52:24 +000039{
40 ResetOptionValues();
41}
42
43CommandObjectDisassemble::CommandOptions::~CommandOptions ()
44{
45}
46
47Error
48CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
49{
50 Error error;
51
52 char short_option = (char) m_getopt_table[option_idx].val;
53
54 switch (short_option)
55 {
56 case 'm':
57 show_mixed = true;
58 break;
59
60 case 'c':
61 num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
62 break;
63
64 case 'b':
65 show_bytes = true;
66 break;
67
Jim Ingham34e9a982010-06-15 18:47:14 +000068 case 's':
69 m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
70 if (m_start_addr == LLDB_INVALID_ADDRESS)
71 m_start_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
Chris Lattner24943d22010-06-08 16:52:24 +000072
Jim Ingham34e9a982010-06-15 18:47:14 +000073 if (m_start_addr == LLDB_INVALID_ADDRESS)
74 error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", optarg);
75 break;
76 case 'e':
77 m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
78 if (m_end_addr == LLDB_INVALID_ADDRESS)
79 m_end_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
80
81 if (m_end_addr == LLDB_INVALID_ADDRESS)
82 error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", optarg);
Chris Lattner24943d22010-06-08 16:52:24 +000083 break;
84
85 case 'n':
86 m_func_name = option_arg;
87 break;
88
89 case 'r':
90 raw = true;
91 break;
92
Johnny Chen61c1b8b2010-10-29 19:33:40 +000093 case 'f':
94 // The default action is to disassemble the function for the current frame.
95 // There's no need to set any flag.
96 break;
97
Chris Lattner24943d22010-06-08 16:52:24 +000098 default:
99 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
100 break;
101 }
102
103 return error;
104}
105
106void
107CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
108{
109 Options::ResetOptionValues();
110 show_mixed = false;
111 show_bytes = false;
112 num_lines_context = 0;
113 m_func_name.clear();
Jim Ingham34e9a982010-06-15 18:47:14 +0000114 m_start_addr = LLDB_INVALID_ADDRESS;
115 m_end_addr = LLDB_INVALID_ADDRESS;
Sean Callanan944be702010-06-17 00:32:05 +0000116 raw = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000117}
118
119const lldb::OptionDefinition*
120CommandObjectDisassemble::CommandOptions::GetDefinitions ()
121{
122 return g_option_table;
123}
124
125lldb::OptionDefinition
126CommandObjectDisassemble::CommandOptions::g_option_table[] =
127{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000128{ LLDB_OPT_SET_ALL, false, "bytes", 'b', no_argument, NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
129{ LLDB_OPT_SET_ALL, false, "context", 'c', required_argument, NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
130{ LLDB_OPT_SET_ALL, false, "mixed", 'm', no_argument, NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
131{ LLDB_OPT_SET_ALL, false, "raw", 'r', no_argument, NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
Chris Lattner24943d22010-06-08 16:52:24 +0000132
Caroline Tice43b014a2010-10-04 22:28:36 +0000133{ LLDB_OPT_SET_1, true, "start-address", 's', required_argument, NULL, 0, eArgTypeStartAddress, "Address at which to start disassembling."},
134{ LLDB_OPT_SET_1, false, "end-address", 'e', required_argument, NULL, 0, eArgTypeEndAddress, "Address at which to end disassembling."},
Chris Lattner24943d22010-06-08 16:52:24 +0000135
Caroline Tice4d6675c2010-10-01 19:59:14 +0000136{ LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
Jim Ingham34e9a982010-06-15 18:47:14 +0000137
Johnny Chen61c1b8b2010-10-29 19:33:40 +0000138{ LLDB_OPT_SET_3, true, "current-frame", 'f', no_argument, NULL, 0, eArgTypeNone, "Disassemble entire contents of the current frame's function."},
Chris Lattner24943d22010-06-08 16:52:24 +0000139
Caroline Tice4d6675c2010-10-01 19:59:14 +0000140{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000141};
142
143
144
145//-------------------------------------------------------------------------
146// CommandObjectDisassemble
147//-------------------------------------------------------------------------
148
Greg Clayton238c0a12010-09-18 01:14:36 +0000149CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) :
150 CommandObject (interpreter,
151 "disassemble",
152 "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.",
153 "disassemble [<cmd-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +0000154{
155}
156
157CommandObjectDisassemble::~CommandObjectDisassemble()
158{
159}
160
Chris Lattner24943d22010-06-08 16:52:24 +0000161bool
162CommandObjectDisassemble::Execute
163(
164 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000165 CommandReturnObject &result
166)
167{
Greg Clayton238c0a12010-09-18 01:14:36 +0000168 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000169 if (target == NULL)
170 {
171 result.AppendError ("invalid target, set executable file using 'file' command");
172 result.SetStatus (eReturnStatusFailed);
173 return false;
174 }
175
176 ArchSpec arch(target->GetArchitecture());
177 if (!arch.IsValid())
178 {
179 result.AppendError ("target needs valid architecure in order to be able to disassemble");
180 result.SetStatus (eReturnStatusFailed);
181 return false;
182 }
183
184 Disassembler *disassembler = Disassembler::FindPlugin(arch);
185
186 if (disassembler == NULL)
187 {
Greg Clayton940b1032011-02-23 00:35:02 +0000188 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.GetArchitectureName());
Chris Lattner24943d22010-06-08 16:52:24 +0000189 result.SetStatus (eReturnStatusFailed);
190 return false;
191 }
192
193 result.SetStatus (eReturnStatusSuccessFinishResult);
194
Greg Clayton70436352010-06-30 23:03:03 +0000195 if (command.GetArgumentCount() != 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000196 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000197 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
198 GetOptions()->GenerateOptionUsage (m_interpreter,
199 result.GetErrorStream(),
200 this);
201
Jim Ingham34e9a982010-06-15 18:47:14 +0000202 result.SetStatus (eReturnStatusFailed);
203 return false;
204 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000205 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Chris Lattner24943d22010-06-08 16:52:24 +0000206
Greg Clayton70436352010-06-30 23:03:03 +0000207 if (m_options.show_mixed && m_options.num_lines_context == 0)
Greg Clayton1924e242010-09-15 05:51:24 +0000208 m_options.num_lines_context = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000209
Greg Clayton70436352010-06-30 23:03:03 +0000210 if (!m_options.m_func_name.empty())
211 {
212 ConstString name(m_options.m_func_name.c_str());
213
Greg Clayton238c0a12010-09-18 01:14:36 +0000214 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
Greg Clayton70436352010-06-30 23:03:03 +0000215 arch,
216 exe_ctx,
217 name,
218 NULL, // Module *
219 m_options.show_mixed ? m_options.num_lines_context : 0,
220 m_options.show_bytes,
Sean Callanana846cc32011-03-10 23:35:12 +0000221 m_options.raw,
Greg Clayton70436352010-06-30 23:03:03 +0000222 result.GetOutputStream()))
Chris Lattner24943d22010-06-08 16:52:24 +0000223 {
Greg Clayton70436352010-06-30 23:03:03 +0000224 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000225 }
226 else
227 {
228 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
229 result.SetStatus (eReturnStatusFailed);
Chris Lattner24943d22010-06-08 16:52:24 +0000230 }
Greg Clayton70436352010-06-30 23:03:03 +0000231 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000232 else
Chris Lattner24943d22010-06-08 16:52:24 +0000233 {
Greg Clayton70436352010-06-30 23:03:03 +0000234 AddressRange range;
235 if (m_options.m_start_addr != LLDB_INVALID_ADDRESS)
236 {
237 range.GetBaseAddress().SetOffset (m_options.m_start_addr);
238 if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
239 {
240 if (m_options.m_end_addr < m_options.m_start_addr)
241 {
242 result.AppendErrorWithFormat ("End address before start address.\n");
243 result.SetStatus (eReturnStatusFailed);
244 return false;
245 }
246 range.SetByteSize (m_options.m_end_addr - m_options.m_start_addr);
247 }
248 else
249 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
250 }
251 else
252 {
Johnny Chen61c1b8b2010-10-29 19:33:40 +0000253 // The default action is to disassemble the current frame function.
Greg Clayton70436352010-06-30 23:03:03 +0000254 if (exe_ctx.frame)
255 {
Jason Molenda8f0ad082010-11-04 09:43:27 +0000256 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Greg Clayton70436352010-06-30 23:03:03 +0000257 if (sc.function)
258 range = sc.function->GetAddressRange();
259 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
260 range = *sc.symbol->GetAddressRangePtr();
261 else
Greg Claytonb04e7a82010-08-24 21:05:24 +0000262 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Clayton70436352010-06-30 23:03:03 +0000263 }
264 else
265 {
266 result.AppendError ("invalid frame");
267 result.SetStatus (eReturnStatusFailed);
268 return false;
269 }
270 }
271 if (range.GetByteSize() == 0)
272 range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
273
Greg Clayton238c0a12010-09-18 01:14:36 +0000274 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
Greg Clayton70436352010-06-30 23:03:03 +0000275 arch,
276 exe_ctx,
277 range,
278 m_options.show_mixed ? m_options.num_lines_context : 0,
279 m_options.show_bytes,
Sean Callanana846cc32011-03-10 23:35:12 +0000280 m_options.raw,
Greg Clayton70436352010-06-30 23:03:03 +0000281 result.GetOutputStream()))
282 {
283 result.SetStatus (eReturnStatusSuccessFinishResult);
284 }
285 else
286 {
287 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
288 result.SetStatus (eReturnStatusFailed);
289 }
Chris Lattner24943d22010-06-08 16:52:24 +0000290 }
291
Jim Ingham34e9a982010-06-15 18:47:14 +0000292 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +0000293}