blob: 9e01fe88fd73e502cfe89aed86614380e01742a0 [file] [log] [blame]
Chris Lattner30fdc8d2010-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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000014#include "CommandObjectDisassemble.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Core/AddressRange.h"
Greg Clayton1f746072012-08-29 21:13:06 +000016#include "lldb/Core/Disassembler.h"
Jason Molenda801237a2013-04-11 03:14:01 +000017#include "lldb/Core/Module.h"
Greg Clayton1f746072012-08-29 21:13:06 +000018#include "lldb/Core/SourceManager.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000019#include "lldb/Host/StringConvert.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Interpreter/CommandCompletions.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000023#include "lldb/Interpreter/Options.h"
Greg Clayton1f746072012-08-29 21:13:06 +000024#include "lldb/Symbol/Function.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Symbol/Symbol.h"
26#include "lldb/Target/Process.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000027#include "lldb/Target/SectionLoadList.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000028#include "lldb/Target/StackFrame.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Target/Target.h"
30
31#define DEFAULT_DISASM_BYTE_SIZE 32
Jim Ingham37023b02011-03-22 01:48:42 +000032#define DEFAULT_DISASM_NUM_INS 4
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Greg Claytoneb0103f2011-04-07 22:46:35 +000037CommandObjectDisassemble::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
Johnny Chen1f1b2692011-04-08 22:15:29 +000038 Options(interpreter),
Jim Ingham37023b02011-03-22 01:48:42 +000039 num_lines_context(0),
40 num_instructions (0),
Greg Clayton32e0a752011-03-30 18:16:51 +000041 func_name(),
Greg Clayton1fb2e7d2012-12-14 22:36:35 +000042 current_function (false),
Greg Clayton32e0a752011-03-30 18:16:51 +000043 start_addr(),
44 end_addr (),
45 at_pc (false),
46 frame_line (false),
47 plugin_name (),
Jim Ingham0f063ba2013-03-02 00:26:47 +000048 flavor_string(),
Jim Ingham3555b5d2011-09-01 01:11:04 +000049 arch(),
Jason Molenda801237a2013-04-11 03:14:01 +000050 some_location_specified (false),
51 symbol_containing_addr ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052{
Greg Claytonf6b8b582011-04-13 00:18:08 +000053 OptionParsingStarting();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054}
55
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000056CommandObjectDisassemble::CommandOptions::~CommandOptions() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057
58Error
Greg Claytonf6b8b582011-04-13 00:18:08 +000059CommandObjectDisassemble::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060{
61 Error error;
62
Greg Clayton3bcdfc02012-12-04 00:32:51 +000063 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064
Jim Ingham37023b02011-03-22 01:48:42 +000065 bool success;
66
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067 switch (short_option)
68 {
69 case 'm':
70 show_mixed = true;
71 break;
72
Greg Clayton357132e2011-03-26 19:14:58 +000073 case 'C':
Vince Harron5275aaa2015-01-15 20:08:35 +000074 num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success);
Jim Ingham37023b02011-03-22 01:48:42 +000075 if (!success)
Greg Clayton86edbf42011-10-26 00:56:27 +000076 error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg);
Jim Ingham37023b02011-03-22 01:48:42 +000077 break;
78
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 case 'c':
Vince Harron5275aaa2015-01-15 20:08:35 +000080 num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success);
Jim Ingham37023b02011-03-22 01:48:42 +000081 if (!success)
Greg Clayton86edbf42011-10-26 00:56:27 +000082 error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083 break;
84
85 case 'b':
86 show_bytes = true;
87 break;
88
Jim Ingham86511212010-06-15 18:47:14 +000089 case 's':
Greg Claytonb9d5df52012-12-06 22:49:16 +000090 {
91 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
92 start_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
93 if (start_addr != LLDB_INVALID_ADDRESS)
94 some_location_specified = true;
95 }
Jim Ingham86511212010-06-15 18:47:14 +000096 break;
97 case 'e':
Greg Claytonb9d5df52012-12-06 22:49:16 +000098 {
99 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
100 end_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
101 if (end_addr != LLDB_INVALID_ADDRESS)
102 some_location_specified = true;
103 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000105
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 case 'n':
Greg Clayton32e0a752011-03-30 18:16:51 +0000107 func_name.assign (option_arg);
Jim Ingham3555b5d2011-09-01 01:11:04 +0000108 some_location_specified = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 break;
110
Jim Ingham37023b02011-03-22 01:48:42 +0000111 case 'p':
Greg Clayton32e0a752011-03-30 18:16:51 +0000112 at_pc = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000113 some_location_specified = true;
Greg Clayton32e0a752011-03-30 18:16:51 +0000114 break;
115
116 case 'l':
117 frame_line = true;
118 // Disassemble the current source line kind of implies showing mixed
119 // source code context.
120 show_mixed = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000121 some_location_specified = true;
Jim Ingham37023b02011-03-22 01:48:42 +0000122 break;
123
Greg Clayton1080edbc2011-03-25 18:03:16 +0000124 case 'P':
Greg Clayton32e0a752011-03-30 18:16:51 +0000125 plugin_name.assign (option_arg);
Greg Clayton1080edbc2011-03-25 18:03:16 +0000126 break;
127
Jim Ingham0f063ba2013-03-02 00:26:47 +0000128 case 'F':
129 {
130 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
131 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86
132 || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64)
133 {
134 flavor_string.assign (option_arg);
135 }
136 else
137 error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets.");
138 break;
139 }
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000140
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141 case 'r':
142 raw = true;
143 break;
144
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000145 case 'f':
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000146 current_function = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000147 some_location_specified = true;
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000148 break;
149
Jason Molenda801237a2013-04-11 03:14:01 +0000150 case 'A':
Greg Clayton70512312012-05-08 01:45:38 +0000151 if (!arch.SetTriple (option_arg, m_interpreter.GetPlatform (true).get()))
152 arch.SetTriple (option_arg);
Greg Clayton357132e2011-03-26 19:14:58 +0000153 break;
154
Jason Molenda801237a2013-04-11 03:14:01 +0000155 case 'a':
156 {
157 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
158 symbol_containing_addr = Args::StringToAddress(&exe_ctx, option_arg, LLDB_INVALID_ADDRESS, &error);
159 if (symbol_containing_addr != LLDB_INVALID_ADDRESS)
160 {
161 some_location_specified = true;
162 }
163 }
164 break;
165
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000167 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000168 break;
169 }
170
171 return error;
172}
173
174void
Greg Claytonf6b8b582011-04-13 00:18:08 +0000175CommandObjectDisassemble::CommandOptions::OptionParsingStarting ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000176{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177 show_mixed = false;
178 show_bytes = false;
179 num_lines_context = 0;
Jim Ingham37023b02011-03-22 01:48:42 +0000180 num_instructions = 0;
Greg Clayton32e0a752011-03-30 18:16:51 +0000181 func_name.clear();
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000182 current_function = false;
Greg Clayton32e0a752011-03-30 18:16:51 +0000183 at_pc = false;
184 frame_line = false;
185 start_addr = LLDB_INVALID_ADDRESS;
186 end_addr = LLDB_INVALID_ADDRESS;
Jason Molenda801237a2013-04-11 03:14:01 +0000187 symbol_containing_addr = LLDB_INVALID_ADDRESS;
Sean Callanana68c1a22010-06-17 00:32:05 +0000188 raw = false;
Greg Clayton32e0a752011-03-30 18:16:51 +0000189 plugin_name.clear();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000190
191 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
192
193 // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor
194 // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the
195 // only disassembler plugin we have...
196 if (target)
197 {
198 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86
199 || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64)
200 {
201 flavor_string.assign(target->GetDisassemblyFlavor());
202 }
203 else
204 flavor_string.assign ("default");
205
206 }
207 else
208 flavor_string.assign("default");
209
Greg Clayton32e0a752011-03-30 18:16:51 +0000210 arch.Clear();
Jim Ingham3555b5d2011-09-01 01:11:04 +0000211 some_location_specified = false;
212}
213
214Error
215CommandObjectDisassemble::CommandOptions::OptionParsingFinished ()
216{
217 if (!some_location_specified)
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000218 current_function = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000219 return Error();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220}
221
Greg Claytone0d378b2011-03-24 21:19:54 +0000222const OptionDefinition*
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223CommandObjectDisassemble::CommandOptions::GetDefinitions ()
224{
225 return g_option_table;
226}
227
Greg Claytone0d378b2011-03-24 21:19:54 +0000228OptionDefinition
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000229CommandObjectDisassemble::CommandOptions::g_option_table[] =
230{
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000231{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
232{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."},
233{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."},
234{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
235{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
236{ LLDB_OPT_SET_ALL, false, "flavor" , 'F', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
Zachary Turnerd37221d2014-07-09 16:31:49 +0000237 "Currently the only valid options are default, and for Intel"
238 " architectures, att and intel."},
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000239{ LLDB_OPT_SET_ALL, false, "arch" , 'A', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeArchitecture,"Specify the architecture to use from cross disassembly."},
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000240{ LLDB_OPT_SET_1 |
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000241 LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."},
242{ LLDB_OPT_SET_1 , false, "end-address" , 'e', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000243{ LLDB_OPT_SET_2 |
244 LLDB_OPT_SET_3 |
245 LLDB_OPT_SET_4 |
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000246 LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."},
247{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
Zachary Turnerd37221d2014-07-09 16:31:49 +0000248 "Disassemble entire contents of the given function name."},
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000249{ LLDB_OPT_SET_4 , false, "frame" , 'f', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
250{ LLDB_OPT_SET_5 , false, "pc" , 'p', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc."},
251{ LLDB_OPT_SET_6 , false, "line" , 'l', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line table information, else disassemble around the pc."},
252{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
253{ 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000254};
255
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256//-------------------------------------------------------------------------
257// CommandObjectDisassemble
258//-------------------------------------------------------------------------
259
Greg Claytona7015092010-09-18 01:14:36 +0000260CommandObjectDisassemble::CommandObjectDisassemble (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000261 CommandObjectParsed (interpreter,
262 "disassemble",
263 "Disassemble bytes in the current function, or elsewhere in the executable program as specified by the user.",
264 "disassemble [<cmd-options>]"),
Greg Claytoneb0103f2011-04-07 22:46:35 +0000265 m_options (interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000266{
267}
268
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000269CommandObjectDisassemble::~CommandObjectDisassemble() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271bool
Jim Ingham5a988412012-06-08 21:56:10 +0000272CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273{
Greg Claytona7015092010-09-18 01:14:36 +0000274 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000275 if (target == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000277 result.AppendError ("invalid target, create a debug target using the 'target create' command");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278 result.SetStatus (eReturnStatusFailed);
279 return false;
280 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000281 if (!m_options.arch.IsValid())
282 m_options.arch = target->GetArchitecture();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283
Greg Clayton32e0a752011-03-30 18:16:51 +0000284 if (!m_options.arch.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000285 {
Jason Molenda125adcf02015-09-04 03:40:29 +0000286 result.AppendError ("use the --arch option or set the target architecture to disassemble");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000287 result.SetStatus (eReturnStatusFailed);
288 return false;
289 }
290
Greg Clayton1080edbc2011-03-25 18:03:16 +0000291 const char *plugin_name = m_options.GetPluginName ();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000292 const char *flavor_string = m_options.GetFlavorString();
293
294 DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295
Sean Callanan9a028512012-08-09 00:50:26 +0000296 if (!disassembler)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000297 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000298 if (plugin_name)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000299 {
300 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
Greg Clayton357132e2011-03-26 19:14:58 +0000301 plugin_name,
Greg Clayton32e0a752011-03-30 18:16:51 +0000302 m_options.arch.GetArchitectureName());
Jim Ingham0f063ba2013-03-02 00:26:47 +0000303 }
Greg Clayton1080edbc2011-03-25 18:03:16 +0000304 else
Greg Clayton357132e2011-03-26 19:14:58 +0000305 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n",
Greg Clayton32e0a752011-03-30 18:16:51 +0000306 m_options.arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307 result.SetStatus (eReturnStatusFailed);
308 return false;
309 }
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000310 else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string))
Jim Ingham0f063ba2013-03-02 00:26:47 +0000311 result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312
313 result.SetStatus (eReturnStatusSuccessFinishResult);
314
Greg Claytondda4f7b2010-06-30 23:03:03 +0000315 if (command.GetArgumentCount() != 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000316 {
Greg Claytona7015092010-09-18 01:14:36 +0000317 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
Greg Claytoneb0103f2011-04-07 22:46:35 +0000318 GetOptions()->GenerateOptionUsage (result.GetErrorStream(), this);
Jim Ingham86511212010-06-15 18:47:14 +0000319 result.SetStatus (eReturnStatusFailed);
320 return false;
321 }
Jim Ingham37023b02011-03-22 01:48:42 +0000322
Greg Claytondda4f7b2010-06-30 23:03:03 +0000323 if (m_options.show_mixed && m_options.num_lines_context == 0)
Greg Clayton6dbd3982010-09-15 05:51:24 +0000324 m_options.num_lines_context = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325
Greg Claytonb10d72f2011-06-28 19:01:40 +0000326 // Always show the PC in the disassembly
327 uint32_t options = Disassembler::eOptionMarkPCAddress;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000328
Greg Claytonb10d72f2011-06-28 19:01:40 +0000329 // Mark the source line for the current PC only if we are doing mixed source and assembly
330 if (m_options.show_mixed)
331 options |= Disassembler::eOptionMarkPCSourceLine;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000332
333 if (m_options.show_bytes)
334 options |= Disassembler::eOptionShowBytes;
335
336 if (m_options.raw)
337 options |= Disassembler::eOptionRawOuput;
Jim Ingham37023b02011-03-22 01:48:42 +0000338
Greg Clayton32e0a752011-03-30 18:16:51 +0000339 if (!m_options.func_name.empty())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000340 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000341 ConstString name(m_options.func_name.c_str());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000342
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000343 if (Disassembler::Disassemble(m_interpreter.GetDebugger(),
344 m_options.arch,
345 plugin_name,
346 flavor_string,
347 m_exe_ctx,
348 name,
349 nullptr, // Module *
350 m_options.num_instructions,
351 m_options.show_mixed ? m_options.num_lines_context : 0,
352 options,
353 result.GetOutputStream()))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000354 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000355 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 }
357 else
358 {
359 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
360 result.SetStatus (eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000361 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000362 }
Jim Ingham86511212010-06-15 18:47:14 +0000363 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000364 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000365 std::vector<AddressRange> ranges;
Greg Clayton32e0a752011-03-30 18:16:51 +0000366 AddressRange range;
Jason Molendab57e4a12013-11-04 09:33:30 +0000367 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Clayton32e0a752011-03-30 18:16:51 +0000368 if (m_options.frame_line)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000369 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000370 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000371 {
372 result.AppendError ("Cannot disassemble around the current line without a selected frame.\n");
373 result.SetStatus (eReturnStatusFailed);
374 return false;
375 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000376 LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
Greg Clayton32e0a752011-03-30 18:16:51 +0000377 if (pc_line_entry.IsValid())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000378 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000379 range = pc_line_entry.range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000380 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000381 else
Jim Ingham37023b02011-03-22 01:48:42 +0000382 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000383 m_options.at_pc = true; // No line entry, so just disassemble around the current pc
384 m_options.show_mixed = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000385 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000386 }
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000387 else if (m_options.current_function)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000388 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000389 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000390 {
391 result.AppendError ("Cannot disassemble around the current function without a selected frame.\n");
392 result.SetStatus (eReturnStatusFailed);
393 return false;
394 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000395 Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000396 if (symbol)
Greg Claytone7612132012-03-07 21:03:09 +0000397 {
398 range.GetBaseAddress() = symbol->GetAddress();
399 range.SetByteSize(symbol->GetByteSize());
400 }
Jim Ingham3555b5d2011-09-01 01:11:04 +0000401 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000402
403 // Did the "m_options.frame_line" find a valid range already? If so
404 // skip the rest...
405 if (range.GetByteSize() == 0)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000406 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000407 if (m_options.at_pc)
Jim Ingham37023b02011-03-22 01:48:42 +0000408 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000409 if (frame == nullptr)
Jim Ingham37023b02011-03-22 01:48:42 +0000410 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000411 result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
412 result.SetStatus (eReturnStatusFailed);
413 return false;
414 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000415 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Greg Clayton32e0a752011-03-30 18:16:51 +0000416 if (m_options.num_instructions == 0)
417 {
418 // Disassembling at the PC always disassembles some number of instructions (not the whole function).
419 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
420 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000421 ranges.push_back(range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000422 }
423 else
424 {
425 range.GetBaseAddress().SetOffset (m_options.start_addr);
426 if (range.GetBaseAddress().IsValid())
427 {
428 if (m_options.end_addr != LLDB_INVALID_ADDRESS)
Jim Ingham37023b02011-03-22 01:48:42 +0000429 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000430 if (m_options.end_addr <= m_options.start_addr)
431 {
432 result.AppendErrorWithFormat ("End address before start address.\n");
433 result.SetStatus (eReturnStatusFailed);
434 return false;
435 }
436 range.SetByteSize (m_options.end_addr - m_options.start_addr);
Jim Ingham37023b02011-03-22 01:48:42 +0000437 }
Jim Ingham2f4693a2014-04-03 17:16:17 +0000438 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000439 }
Jason Molenda801237a2013-04-11 03:14:01 +0000440 else
441 {
442 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS
Jim Ingham2f2c8762014-03-25 00:15:47 +0000443 && target)
Jason Molenda801237a2013-04-11 03:14:01 +0000444 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000445 if (!target->GetSectionLoadList().IsEmpty())
Jason Molenda801237a2013-04-11 03:14:01 +0000446 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000447 bool failed = false;
448 Address symbol_containing_address;
449 if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
Jason Molenda801237a2013-04-11 03:14:01 +0000450 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000451 ModuleSP module_sp (symbol_containing_address.GetModule());
452 SymbolContext sc;
453 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
454 module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
455 resolve_tail_call_address);
456 if (sc.function || sc.symbol)
457 {
458 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
459 }
460 else
461 {
462 failed = true;
463 }
Jason Molenda801237a2013-04-11 03:14:01 +0000464 }
465 else
466 {
467 failed = true;
468 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000469 if (failed)
470 {
471 result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
472 result.SetStatus (eReturnStatusFailed);
473 return false;
474 }
475 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000476 }
477 else
478 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000479 for (lldb::ModuleSP module_sp : target->GetImages().Modules())
480 {
481 lldb::addr_t file_addr = m_options.symbol_containing_addr;
482 Address file_address;
483 if (module_sp->ResolveFileAddress(file_addr, file_address))
484 {
485 SymbolContext sc;
486 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
487 module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address);
488 if (sc.function || sc.symbol)
489 {
490 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
491 ranges.push_back(range);
492 }
493 }
494 }
Jason Molenda801237a2013-04-11 03:14:01 +0000495 }
496 }
497 }
Jim Ingham37023b02011-03-22 01:48:42 +0000498 }
499 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000500 else
501 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000502
Jim Ingham37023b02011-03-22 01:48:42 +0000503 if (m_options.num_instructions != 0)
504 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000505 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000506 {
507 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000508 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000509 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000510 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000511 if (sc.function)
Greg Clayton32e0a752011-03-30 18:16:51 +0000512 range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
Greg Claytone7612132012-03-07 21:03:09 +0000513 else if (sc.symbol && sc.symbol->ValueIsAddress())
514 range.GetBaseAddress() = sc.symbol->GetAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000515 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000516 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000517 }
518
Greg Clayton32e0a752011-03-30 18:16:51 +0000519 if (!range.GetBaseAddress().IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000520 {
521 result.AppendError ("invalid frame");
522 result.SetStatus (eReturnStatusFailed);
523 return false;
524 }
525 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000526
527 bool print_sc_header = ranges.size() > 1;
528 for (AddressRange cur_range : ranges)
Jim Ingham37023b02011-03-22 01:48:42 +0000529 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000530 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
531 m_options.arch,
532 plugin_name,
533 flavor_string,
534 m_exe_ctx,
535 cur_range.GetBaseAddress(),
536 m_options.num_instructions,
537 m_options.show_mixed ? m_options.num_lines_context : 0,
538 options,
539 result.GetOutputStream()))
540 {
541 result.SetStatus (eReturnStatusSuccessFinishResult);
542 }
543 else
544 {
545 if (m_options.start_addr != LLDB_INVALID_ADDRESS)
546 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
547 else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
548 result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr);
549 result.SetStatus (eReturnStatusFailed);
550 }
Jim Ingham37023b02011-03-22 01:48:42 +0000551 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000552 if (print_sc_header)
553 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000554 }
555 else
556 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000557 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000558 {
559 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000560 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000561 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000562 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000563 if (sc.function)
564 range = sc.function->GetAddressRange();
Greg Claytone7612132012-03-07 21:03:09 +0000565 else if (sc.symbol && sc.symbol->ValueIsAddress())
566 {
567 range.GetBaseAddress() = sc.symbol->GetAddress();
568 range.SetByteSize (sc.symbol->GetByteSize());
569 }
Jim Ingham37023b02011-03-22 01:48:42 +0000570 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000571 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000572 }
573 else
574 {
575 result.AppendError ("invalid frame");
576 result.SetStatus (eReturnStatusFailed);
577 return false;
578 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000579 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000580 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000581
582 bool print_sc_header = ranges.size() > 1;
583 for (AddressRange cur_range : ranges)
584 {
585 if (cur_range.GetByteSize() == 0)
586 cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
Jim Ingham37023b02011-03-22 01:48:42 +0000587
Jim Ingham2f2c8762014-03-25 00:15:47 +0000588 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
589 m_options.arch,
590 plugin_name,
591 flavor_string,
592 m_exe_ctx,
593 cur_range,
594 m_options.num_instructions,
595 m_options.show_mixed ? m_options.num_lines_context : 0,
596 options,
597 result.GetOutputStream()))
598 {
599 result.SetStatus (eReturnStatusSuccessFinishResult);
600 }
601 else
602 {
603 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
604 result.SetStatus (eReturnStatusFailed);
605 }
606 if (print_sc_header)
607 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000608 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000609 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000610 }
611
Jim Ingham86511212010-06-15 18:47:14 +0000612 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000613}