blob: 74c27e39090730f59b3aeef99d03d95a073de976 [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
Jim Inghamaa3e3e12011-03-22 01:48:42 +000030#define DEFAULT_DISASM_NUM_INS 4
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
35CommandObjectDisassemble::CommandOptions::CommandOptions () :
36 Options(),
Jim Inghamaa3e3e12011-03-22 01:48:42 +000037 num_lines_context(0),
38 num_instructions (0),
Chris Lattner24943d22010-06-08 16:52:24 +000039 m_func_name(),
Jim Ingham34e9a982010-06-15 18:47:14 +000040 m_start_addr(),
Jim Inghamaa3e3e12011-03-22 01:48:42 +000041 m_end_addr (),
Greg Clayton149731c2011-03-25 18:03:16 +000042 m_at_pc (false),
Greg Clayton889fbd02011-03-26 19:14:58 +000043 m_plugin_name (),
44 m_arch()
Chris Lattner24943d22010-06-08 16:52:24 +000045{
46 ResetOptionValues();
47}
48
49CommandObjectDisassemble::CommandOptions::~CommandOptions ()
50{
51}
52
53Error
54CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
55{
56 Error error;
57
58 char short_option = (char) m_getopt_table[option_idx].val;
59
Jim Inghamaa3e3e12011-03-22 01:48:42 +000060 bool success;
61
Chris Lattner24943d22010-06-08 16:52:24 +000062 switch (short_option)
63 {
64 case 'm':
65 show_mixed = true;
66 break;
67
Greg Clayton889fbd02011-03-26 19:14:58 +000068 case 'C':
Jim Inghamaa3e3e12011-03-22 01:48:42 +000069 num_lines_context = Args::StringToUInt32(option_arg, 0, 0, &success);
70 if (!success)
71 error.SetErrorStringWithFormat ("Invalid num context lines string: \"%s\".\n", option_arg);
72 break;
73
Chris Lattner24943d22010-06-08 16:52:24 +000074 case 'c':
Jim Inghamaa3e3e12011-03-22 01:48:42 +000075 num_instructions = Args::StringToUInt32(option_arg, 0, 0, &success);
76 if (!success)
77 error.SetErrorStringWithFormat ("Invalid num of instructions string: \"%s\".\n", option_arg);
Chris Lattner24943d22010-06-08 16:52:24 +000078 break;
79
80 case 'b':
81 show_bytes = true;
82 break;
83
Jim Ingham34e9a982010-06-15 18:47:14 +000084 case 's':
Jim Inghamaa3e3e12011-03-22 01:48:42 +000085 m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
Jim Ingham34e9a982010-06-15 18:47:14 +000086 if (m_start_addr == LLDB_INVALID_ADDRESS)
Jim Inghamaa3e3e12011-03-22 01:48:42 +000087 m_start_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
Chris Lattner24943d22010-06-08 16:52:24 +000088
Jim Ingham34e9a982010-06-15 18:47:14 +000089 if (m_start_addr == LLDB_INVALID_ADDRESS)
Jim Inghamaa3e3e12011-03-22 01:48:42 +000090 error.SetErrorStringWithFormat ("Invalid start address string '%s'.\n", option_arg);
Jim Ingham34e9a982010-06-15 18:47:14 +000091 break;
92 case 'e':
Jim Inghamaa3e3e12011-03-22 01:48:42 +000093 m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 0);
Jim Ingham34e9a982010-06-15 18:47:14 +000094 if (m_end_addr == LLDB_INVALID_ADDRESS)
Jim Inghamaa3e3e12011-03-22 01:48:42 +000095 m_end_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS, 16);
Jim Ingham34e9a982010-06-15 18:47:14 +000096
97 if (m_end_addr == LLDB_INVALID_ADDRESS)
Jim Inghamaa3e3e12011-03-22 01:48:42 +000098 error.SetErrorStringWithFormat ("Invalid end address string '%s'.\n", option_arg);
Chris Lattner24943d22010-06-08 16:52:24 +000099 break;
100
101 case 'n':
Greg Clayton149731c2011-03-25 18:03:16 +0000102 m_func_name.assign (option_arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000103 break;
104
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000105 case 'p':
106 m_at_pc = true;
107 break;
108
Greg Clayton149731c2011-03-25 18:03:16 +0000109 case 'P':
110 m_plugin_name.assign (option_arg);
111 break;
112
Chris Lattner24943d22010-06-08 16:52:24 +0000113 case 'r':
114 raw = true;
115 break;
116
Johnny Chen61c1b8b2010-10-29 19:33:40 +0000117 case 'f':
118 // The default action is to disassemble the function for the current frame.
119 // There's no need to set any flag.
120 break;
121
Greg Clayton889fbd02011-03-26 19:14:58 +0000122 case 'a':
123 m_arch.SetTriple (option_arg);
124 break;
125
Chris Lattner24943d22010-06-08 16:52:24 +0000126 default:
127 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
128 break;
129 }
130
131 return error;
132}
133
134void
135CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
136{
137 Options::ResetOptionValues();
138 show_mixed = false;
139 show_bytes = false;
140 num_lines_context = 0;
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000141 num_instructions = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000142 m_func_name.clear();
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000143 m_at_pc = false;
Jim Ingham34e9a982010-06-15 18:47:14 +0000144 m_start_addr = LLDB_INVALID_ADDRESS;
145 m_end_addr = LLDB_INVALID_ADDRESS;
Sean Callanan944be702010-06-17 00:32:05 +0000146 raw = false;
Greg Clayton149731c2011-03-25 18:03:16 +0000147 m_plugin_name.clear();
Greg Clayton889fbd02011-03-26 19:14:58 +0000148 m_arch.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000149}
150
Greg Claytonb3448432011-03-24 21:19:54 +0000151const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000152CommandObjectDisassemble::CommandOptions::GetDefinitions ()
153{
154 return g_option_table;
155}
156
Greg Claytonb3448432011-03-24 21:19:54 +0000157OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000158CommandObjectDisassemble::CommandOptions::g_option_table[] =
159{
Greg Clayton889fbd02011-03-26 19:14:58 +0000160{ LLDB_OPT_SET_ALL , false , "bytes", 'b', no_argument , NULL, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
161{ LLDB_OPT_SET_ALL , false , "context", 'C', required_argument , NULL, 0, eArgTypeNumLines, "Number of context lines of source to show."},
162{ LLDB_OPT_SET_ALL , false , "mixed", 'm', no_argument , NULL, 0, eArgTypeNone, "Enable mixed source and assembly display."},
163{ LLDB_OPT_SET_ALL , false , "raw", 'r', no_argument , NULL, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
164{ LLDB_OPT_SET_ALL , false , "plugin", 'P', required_argument , NULL, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
165{ LLDB_OPT_SET_ALL , false , "arch", 'a', required_argument , NULL, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
166{ LLDB_OPT_SET_1 |
167 LLDB_OPT_SET_2 , true , "start-address" , 's', required_argument , NULL, 0, eArgTypeStartAddress,"Address at which to start disassembling."},
168{ LLDB_OPT_SET_1 , false , "end-address" , 'e', required_argument , NULL, 0, eArgTypeEndAddress, "Address at which to end disassembling."},
169{ LLDB_OPT_SET_2 |
170 LLDB_OPT_SET_3 |
171 LLDB_OPT_SET_4 |
172 LLDB_OPT_SET_5 , false , "count", 'c', required_argument , NULL, 0, eArgTypeNumLines, "Number of instructions to display."},
173{ LLDB_OPT_SET_3 , true , "name", 'n', required_argument , NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
174{ LLDB_OPT_SET_4 , true , "frame", 'f', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
175{ LLDB_OPT_SET_5 , true , "pc", 'p', no_argument , NULL, 0, eArgTypeNone, "Disassemble from the current pc."},
176{ 0 , false , NULL, 0, 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000177};
178
179
180
181//-------------------------------------------------------------------------
182// CommandObjectDisassemble
183//-------------------------------------------------------------------------
184
Greg Clayton238c0a12010-09-18 01:14:36 +0000185CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) :
186 CommandObject (interpreter,
187 "disassemble",
188 "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.",
189 "disassemble [<cmd-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +0000190{
191}
192
193CommandObjectDisassemble::~CommandObjectDisassemble()
194{
195}
196
Chris Lattner24943d22010-06-08 16:52:24 +0000197bool
198CommandObjectDisassemble::Execute
199(
200 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000201 CommandReturnObject &result
202)
203{
Greg Clayton238c0a12010-09-18 01:14:36 +0000204 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000205 if (target == NULL)
206 {
207 result.AppendError ("invalid target, set executable file using 'file' command");
208 result.SetStatus (eReturnStatusFailed);
209 return false;
210 }
Greg Clayton889fbd02011-03-26 19:14:58 +0000211 if (!m_options.m_arch.IsValid())
212 m_options.m_arch = target->GetArchitecture();
Chris Lattner24943d22010-06-08 16:52:24 +0000213
Greg Clayton889fbd02011-03-26 19:14:58 +0000214 if (!m_options.m_arch.IsValid())
Chris Lattner24943d22010-06-08 16:52:24 +0000215 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000216 result.AppendError ("use the --arch option or set the target architecure to disassemble");
Chris Lattner24943d22010-06-08 16:52:24 +0000217 result.SetStatus (eReturnStatusFailed);
218 return false;
219 }
220
Greg Clayton149731c2011-03-25 18:03:16 +0000221 const char *plugin_name = m_options.GetPluginName ();
Greg Clayton889fbd02011-03-26 19:14:58 +0000222 Disassembler *disassembler = Disassembler::FindPlugin(m_options.m_arch, plugin_name);
Chris Lattner24943d22010-06-08 16:52:24 +0000223
224 if (disassembler == NULL)
225 {
Greg Clayton149731c2011-03-25 18:03:16 +0000226 if (plugin_name)
Greg Clayton889fbd02011-03-26 19:14:58 +0000227 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
228 plugin_name,
229 m_options.m_arch.GetArchitectureName());
Greg Clayton149731c2011-03-25 18:03:16 +0000230 else
Greg Clayton889fbd02011-03-26 19:14:58 +0000231 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n",
232 m_options.m_arch.GetArchitectureName());
Chris Lattner24943d22010-06-08 16:52:24 +0000233 result.SetStatus (eReturnStatusFailed);
234 return false;
235 }
236
237 result.SetStatus (eReturnStatusSuccessFinishResult);
238
Greg Clayton70436352010-06-30 23:03:03 +0000239 if (command.GetArgumentCount() != 0)
Chris Lattner24943d22010-06-08 16:52:24 +0000240 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000241 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
242 GetOptions()->GenerateOptionUsage (m_interpreter,
243 result.GetErrorStream(),
244 this);
245
Jim Ingham34e9a982010-06-15 18:47:14 +0000246 result.SetStatus (eReturnStatusFailed);
247 return false;
248 }
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000249
Greg Clayton70436352010-06-30 23:03:03 +0000250 if (m_options.show_mixed && m_options.num_lines_context == 0)
Greg Clayton1924e242010-09-15 05:51:24 +0000251 m_options.num_lines_context = 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000252
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000253 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
254
Greg Clayton70436352010-06-30 23:03:03 +0000255 if (!m_options.m_func_name.empty())
256 {
257 ConstString name(m_options.m_func_name.c_str());
258
Greg Clayton238c0a12010-09-18 01:14:36 +0000259 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
Greg Clayton889fbd02011-03-26 19:14:58 +0000260 m_options.m_arch,
Greg Clayton149731c2011-03-25 18:03:16 +0000261 plugin_name,
Greg Clayton70436352010-06-30 23:03:03 +0000262 exe_ctx,
263 name,
264 NULL, // Module *
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000265 m_options.num_instructions,
Greg Clayton70436352010-06-30 23:03:03 +0000266 m_options.show_mixed ? m_options.num_lines_context : 0,
267 m_options.show_bytes,
Sean Callanana846cc32011-03-10 23:35:12 +0000268 m_options.raw,
Greg Clayton70436352010-06-30 23:03:03 +0000269 result.GetOutputStream()))
Chris Lattner24943d22010-06-08 16:52:24 +0000270 {
Greg Clayton70436352010-06-30 23:03:03 +0000271 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner24943d22010-06-08 16:52:24 +0000272 }
273 else
274 {
275 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
276 result.SetStatus (eReturnStatusFailed);
Chris Lattner24943d22010-06-08 16:52:24 +0000277 }
Greg Clayton70436352010-06-30 23:03:03 +0000278 }
Jim Ingham34e9a982010-06-15 18:47:14 +0000279 else
Chris Lattner24943d22010-06-08 16:52:24 +0000280 {
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000281 Address start_addr;
282 lldb::addr_t range_byte_size = DEFAULT_DISASM_BYTE_SIZE;
283
284 if (m_options.m_at_pc)
Greg Clayton70436352010-06-30 23:03:03 +0000285 {
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000286 if (exe_ctx.frame == NULL)
Greg Clayton70436352010-06-30 23:03:03 +0000287 {
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000288 result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
Greg Clayton70436352010-06-30 23:03:03 +0000289 result.SetStatus (eReturnStatusFailed);
290 return false;
291 }
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000292 start_addr = exe_ctx.frame->GetFrameCodeAddress();
293 if (m_options.num_instructions == 0)
294 {
295 // Disassembling at the PC always disassembles some number of instructions (not the whole function).
296 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
297 }
Greg Clayton70436352010-06-30 23:03:03 +0000298 }
299 else
300 {
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000301 start_addr.SetOffset (m_options.m_start_addr);
302 if (start_addr.IsValid())
303 {
304 if (m_options.m_end_addr != LLDB_INVALID_ADDRESS)
305 {
306 if (m_options.m_end_addr < m_options.m_start_addr)
307 {
308 result.AppendErrorWithFormat ("End address before start address.\n");
309 result.SetStatus (eReturnStatusFailed);
310 return false;
311 }
312 range_byte_size = m_options.m_end_addr - m_options.m_start_addr;
313 }
314 }
315 }
316
317 if (m_options.num_instructions != 0)
318 {
319 if (!start_addr.IsValid())
320 {
321 // The default action is to disassemble the current frame function.
322 if (exe_ctx.frame)
323 {
324 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
325 if (sc.function)
326 start_addr = sc.function->GetAddressRange().GetBaseAddress();
327 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
328 start_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress();
329 else
330 start_addr = exe_ctx.frame->GetFrameCodeAddress();
331 }
332
333 if (!start_addr.IsValid())
334 {
335 result.AppendError ("invalid frame");
336 result.SetStatus (eReturnStatusFailed);
337 return false;
338 }
339 }
340
341 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
Greg Clayton889fbd02011-03-26 19:14:58 +0000342 m_options.m_arch,
Greg Clayton149731c2011-03-25 18:03:16 +0000343 plugin_name,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000344 exe_ctx,
345 start_addr,
346 m_options.num_instructions,
347 m_options.show_mixed ? m_options.num_lines_context : 0,
348 m_options.show_bytes,
349 m_options.raw,
350 result.GetOutputStream()))
351 {
352 result.SetStatus (eReturnStatusSuccessFinishResult);
353 }
354 else
355 {
356 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
357 result.SetStatus (eReturnStatusFailed);
358 }
359 }
360 else
361 {
362 AddressRange range;
363 if (start_addr.IsValid())
364 {
365 range.GetBaseAddress() = start_addr;
366 range.SetByteSize (range_byte_size);
367 }
368 else
369 {
370 // The default action is to disassemble the current frame function.
371 if (exe_ctx.frame)
372 {
373 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
374 if (sc.function)
375 range = sc.function->GetAddressRange();
376 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
377 range = *sc.symbol->GetAddressRangePtr();
378 else
379 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
380 }
381 else
382 {
383 result.AppendError ("invalid frame");
384 result.SetStatus (eReturnStatusFailed);
385 return false;
386 }
387 }
388 if (range.GetByteSize() == 0)
389 range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
390
391 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
Greg Clayton889fbd02011-03-26 19:14:58 +0000392 m_options.m_arch,
Greg Clayton149731c2011-03-25 18:03:16 +0000393 plugin_name,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000394 exe_ctx,
395 range,
396 m_options.num_instructions,
397 m_options.show_mixed ? m_options.num_lines_context : 0,
398 m_options.show_bytes,
399 m_options.raw,
400 result.GetOutputStream()))
401 {
402 result.SetStatus (eReturnStatusSuccessFinishResult);
403 }
404 else
405 {
406 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8llx.\n", m_options.m_start_addr);
407 result.SetStatus (eReturnStatusFailed);
408 }
Greg Clayton70436352010-06-30 23:03:03 +0000409 }
Chris Lattner24943d22010-06-08 16:52:24 +0000410 }
411
Jim Ingham34e9a982010-06-15 18:47:14 +0000412 return result.Succeeded();
Chris Lattner24943d22010-06-08 16:52:24 +0000413}