blob: 796db6152d8bd7b02f4daea6fbffeceb16c8a1be [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
Todd Fialae1cfbc72016-08-11 23:51:28 +000037CommandObjectDisassemble::CommandOptions::CommandOptions() :
38 Options(),
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{
Todd Fialae1cfbc72016-08-11 23:51:28 +000053 OptionParsingStarting(nullptr);
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
Todd Fialae1cfbc72016-08-11 23:51:28 +000059CommandObjectDisassemble::CommandOptions::SetOptionValue(uint32_t option_idx,
60 const char *option_arg,
61 ExecutionContext *execution_context)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000062{
63 Error error;
64
Greg Clayton3bcdfc02012-12-04 00:32:51 +000065 const int short_option = m_getopt_table[option_idx].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066
Jim Ingham37023b02011-03-22 01:48:42 +000067 bool success;
68
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069 switch (short_option)
70 {
71 case 'm':
72 show_mixed = true;
73 break;
74
Greg Clayton357132e2011-03-26 19:14:58 +000075 case 'C':
Vince Harron5275aaa2015-01-15 20:08:35 +000076 num_lines_context = StringConvert::ToUInt32(option_arg, 0, 0, &success);
Jim Ingham37023b02011-03-22 01:48:42 +000077 if (!success)
Greg Clayton86edbf42011-10-26 00:56:27 +000078 error.SetErrorStringWithFormat ("invalid num context lines string: \"%s\"", option_arg);
Jim Ingham37023b02011-03-22 01:48:42 +000079 break;
80
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081 case 'c':
Vince Harron5275aaa2015-01-15 20:08:35 +000082 num_instructions = StringConvert::ToUInt32(option_arg, 0, 0, &success);
Jim Ingham37023b02011-03-22 01:48:42 +000083 if (!success)
Greg Clayton86edbf42011-10-26 00:56:27 +000084 error.SetErrorStringWithFormat ("invalid num of instructions string: \"%s\"", option_arg);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085 break;
86
87 case 'b':
88 show_bytes = true;
89 break;
90
Jim Ingham86511212010-06-15 18:47:14 +000091 case 's':
Greg Claytonb9d5df52012-12-06 22:49:16 +000092 {
Todd Fialae1cfbc72016-08-11 23:51:28 +000093 start_addr = Args::StringToAddress(execution_context, option_arg,
94 LLDB_INVALID_ADDRESS, &error);
Greg Claytonb9d5df52012-12-06 22:49:16 +000095 if (start_addr != LLDB_INVALID_ADDRESS)
96 some_location_specified = true;
97 }
Jim Ingham86511212010-06-15 18:47:14 +000098 break;
99 case 'e':
Greg Claytonb9d5df52012-12-06 22:49:16 +0000100 {
Todd Fialae1cfbc72016-08-11 23:51:28 +0000101 end_addr = Args::StringToAddress(execution_context, option_arg,
102 LLDB_INVALID_ADDRESS, &error);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000103 if (end_addr != LLDB_INVALID_ADDRESS)
104 some_location_specified = true;
105 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 break;
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000107
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108 case 'n':
Greg Clayton32e0a752011-03-30 18:16:51 +0000109 func_name.assign (option_arg);
Jim Ingham3555b5d2011-09-01 01:11:04 +0000110 some_location_specified = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 break;
112
Jim Ingham37023b02011-03-22 01:48:42 +0000113 case 'p':
Greg Clayton32e0a752011-03-30 18:16:51 +0000114 at_pc = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000115 some_location_specified = true;
Greg Clayton32e0a752011-03-30 18:16:51 +0000116 break;
117
118 case 'l':
119 frame_line = true;
120 // Disassemble the current source line kind of implies showing mixed
121 // source code context.
122 show_mixed = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000123 some_location_specified = true;
Jim Ingham37023b02011-03-22 01:48:42 +0000124 break;
125
Greg Clayton1080edbc2011-03-25 18:03:16 +0000126 case 'P':
Greg Clayton32e0a752011-03-30 18:16:51 +0000127 plugin_name.assign (option_arg);
Greg Clayton1080edbc2011-03-25 18:03:16 +0000128 break;
129
Jim Ingham0f063ba2013-03-02 00:26:47 +0000130 case 'F':
131 {
Todd Fialae1cfbc72016-08-11 23:51:28 +0000132 TargetSP target_sp = execution_context ?
133 execution_context->GetTargetSP() : TargetSP();
134 if (target_sp &&
135 (target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86
136 || target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64))
Jim Ingham0f063ba2013-03-02 00:26:47 +0000137 {
138 flavor_string.assign (option_arg);
139 }
140 else
141 error.SetErrorStringWithFormat("Disassembler flavors are currently only supported for x86 and x86_64 targets.");
142 break;
143 }
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000144
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000145 case 'r':
146 raw = true;
147 break;
148
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000149 case 'f':
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000150 current_function = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000151 some_location_specified = true;
Johnny Chen8ceb8ba2010-10-29 19:33:40 +0000152 break;
153
Jason Molenda801237a2013-04-11 03:14:01 +0000154 case 'A':
Todd Fialae1cfbc72016-08-11 23:51:28 +0000155 if (execution_context)
156 {
157 auto target_sp = execution_context ?
158 execution_context->GetTargetSP() : TargetSP();
159 auto platform_sp =
160 target_sp ? target_sp->GetPlatform() : PlatformSP();
161 if (!arch.SetTriple (option_arg, platform_sp.get()))
162 arch.SetTriple (option_arg);
163 }
Greg Clayton357132e2011-03-26 19:14:58 +0000164 break;
165
Jason Molenda801237a2013-04-11 03:14:01 +0000166 case 'a':
167 {
Todd Fialae1cfbc72016-08-11 23:51:28 +0000168 symbol_containing_addr =
169 Args::StringToAddress(execution_context,option_arg,
170 LLDB_INVALID_ADDRESS, &error);
Jason Molenda801237a2013-04-11 03:14:01 +0000171 if (symbol_containing_addr != LLDB_INVALID_ADDRESS)
172 {
173 some_location_specified = true;
174 }
175 }
176 break;
177
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000179 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 break;
181 }
182
183 return error;
184}
185
186void
Todd Fialae1cfbc72016-08-11 23:51:28 +0000187CommandObjectDisassemble::CommandOptions::OptionParsingStarting(
188 ExecutionContext *execution_context)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190 show_mixed = false;
191 show_bytes = false;
192 num_lines_context = 0;
Jim Ingham37023b02011-03-22 01:48:42 +0000193 num_instructions = 0;
Greg Clayton32e0a752011-03-30 18:16:51 +0000194 func_name.clear();
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000195 current_function = false;
Greg Clayton32e0a752011-03-30 18:16:51 +0000196 at_pc = false;
197 frame_line = false;
198 start_addr = LLDB_INVALID_ADDRESS;
199 end_addr = LLDB_INVALID_ADDRESS;
Jason Molenda801237a2013-04-11 03:14:01 +0000200 symbol_containing_addr = LLDB_INVALID_ADDRESS;
Sean Callanana68c1a22010-06-17 00:32:05 +0000201 raw = false;
Greg Clayton32e0a752011-03-30 18:16:51 +0000202 plugin_name.clear();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000203
Todd Fialae1cfbc72016-08-11 23:51:28 +0000204 Target *target =
205 execution_context ? execution_context->GetTargetPtr() : nullptr;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000206
207 // This is a hack till we get the ability to specify features based on architecture. For now GetDisassemblyFlavor
208 // is really only valid for x86 (and for the llvm assembler plugin, but I'm papering over that since that is the
209 // only disassembler plugin we have...
210 if (target)
211 {
212 if (target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86
213 || target->GetArchitecture().GetTriple().getArch() == llvm::Triple::x86_64)
214 {
215 flavor_string.assign(target->GetDisassemblyFlavor());
216 }
217 else
218 flavor_string.assign ("default");
219
220 }
221 else
222 flavor_string.assign("default");
223
Greg Clayton32e0a752011-03-30 18:16:51 +0000224 arch.Clear();
Jim Ingham3555b5d2011-09-01 01:11:04 +0000225 some_location_specified = false;
226}
227
228Error
Todd Fialae1cfbc72016-08-11 23:51:28 +0000229CommandObjectDisassemble::CommandOptions::OptionParsingFinished(
230 ExecutionContext *execution_context)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000231{
232 if (!some_location_specified)
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000233 current_function = true;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000234 return Error();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235}
236
Greg Claytone0d378b2011-03-24 21:19:54 +0000237const OptionDefinition*
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238CommandObjectDisassemble::CommandOptions::GetDefinitions ()
239{
240 return g_option_table;
241}
242
Greg Claytone0d378b2011-03-24 21:19:54 +0000243OptionDefinition
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244CommandObjectDisassemble::CommandOptions::g_option_table[] =
245{
Kate Stoneac9c3a62016-08-26 23:28:47 +0000246 // clang-format off
247 {LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
248 {LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."},
249 {LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."},
250 {LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
251 {LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
252 {LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
253 "Currently the only valid options are default, and for Intel "
254 "architectures, att and intel."},
255 {LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly."},
256 {LLDB_OPT_SET_1 |
257 LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling."},
258 {LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling."},
259 {LLDB_OPT_SET_2 |
260 LLDB_OPT_SET_3 |
261 LLDB_OPT_SET_4 |
262 LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."},
263 {LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name."},
264 {LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function."},
265 {LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc."},
266 {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 "
267 "table information, else disassemble around the pc."},
268 {LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
269 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
270 // clang-format on
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271};
272
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273//-------------------------------------------------------------------------
274// CommandObjectDisassemble
275//-------------------------------------------------------------------------
276
Kate Stone7428a182016-07-14 22:03:10 +0000277CommandObjectDisassemble::CommandObjectDisassemble(CommandInterpreter &interpreter)
278 : CommandObjectParsed(interpreter, "disassemble", "Disassemble specified instructions in the current target. "
279 "Defaults to the current function for the current thread and "
280 "stack frame.",
281 "disassemble [<cmd-options>]"),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000282 m_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283{
284}
285
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000286CommandObjectDisassemble::~CommandObjectDisassemble() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000287
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288bool
Jim Ingham5a988412012-06-08 21:56:10 +0000289CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000290{
Greg Claytona7015092010-09-18 01:14:36 +0000291 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000292 if (target == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000294 result.AppendError ("invalid target, create a debug target using the 'target create' command");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295 result.SetStatus (eReturnStatusFailed);
296 return false;
297 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000298 if (!m_options.arch.IsValid())
299 m_options.arch = target->GetArchitecture();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300
Greg Clayton32e0a752011-03-30 18:16:51 +0000301 if (!m_options.arch.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000302 {
Jason Molenda125adcf02015-09-04 03:40:29 +0000303 result.AppendError ("use the --arch option or set the target architecture to disassemble");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304 result.SetStatus (eReturnStatusFailed);
305 return false;
306 }
307
Greg Clayton1080edbc2011-03-25 18:03:16 +0000308 const char *plugin_name = m_options.GetPluginName ();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000309 const char *flavor_string = m_options.GetFlavorString();
310
311 DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312
Sean Callanan9a028512012-08-09 00:50:26 +0000313 if (!disassembler)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000315 if (plugin_name)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000316 {
317 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
Greg Clayton357132e2011-03-26 19:14:58 +0000318 plugin_name,
Greg Clayton32e0a752011-03-30 18:16:51 +0000319 m_options.arch.GetArchitectureName());
Jim Ingham0f063ba2013-03-02 00:26:47 +0000320 }
Greg Clayton1080edbc2011-03-25 18:03:16 +0000321 else
Greg Clayton357132e2011-03-26 19:14:58 +0000322 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n",
Greg Clayton32e0a752011-03-30 18:16:51 +0000323 m_options.arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324 result.SetStatus (eReturnStatusFailed);
325 return false;
326 }
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000327 else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string))
Jim Ingham0f063ba2013-03-02 00:26:47 +0000328 result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329
330 result.SetStatus (eReturnStatusSuccessFinishResult);
331
Greg Claytondda4f7b2010-06-30 23:03:03 +0000332 if (command.GetArgumentCount() != 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333 {
Greg Claytona7015092010-09-18 01:14:36 +0000334 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
Todd Fialae1cfbc72016-08-11 23:51:28 +0000335 const int terminal_width =
336 GetCommandInterpreter().GetDebugger().GetTerminalWidth();
337 GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
338 terminal_width);
Jim Ingham86511212010-06-15 18:47:14 +0000339 result.SetStatus (eReturnStatusFailed);
340 return false;
341 }
Jim Ingham37023b02011-03-22 01:48:42 +0000342
Greg Claytondda4f7b2010-06-30 23:03:03 +0000343 if (m_options.show_mixed && m_options.num_lines_context == 0)
Greg Clayton6dbd3982010-09-15 05:51:24 +0000344 m_options.num_lines_context = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345
Greg Claytonb10d72f2011-06-28 19:01:40 +0000346 // Always show the PC in the disassembly
347 uint32_t options = Disassembler::eOptionMarkPCAddress;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000348
Greg Claytonb10d72f2011-06-28 19:01:40 +0000349 // Mark the source line for the current PC only if we are doing mixed source and assembly
350 if (m_options.show_mixed)
351 options |= Disassembler::eOptionMarkPCSourceLine;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000352
353 if (m_options.show_bytes)
354 options |= Disassembler::eOptionShowBytes;
355
356 if (m_options.raw)
357 options |= Disassembler::eOptionRawOuput;
Jim Ingham37023b02011-03-22 01:48:42 +0000358
Greg Clayton32e0a752011-03-30 18:16:51 +0000359 if (!m_options.func_name.empty())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000360 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000361 ConstString name(m_options.func_name.c_str());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000362
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000363 if (Disassembler::Disassemble(m_interpreter.GetDebugger(),
364 m_options.arch,
365 plugin_name,
366 flavor_string,
367 m_exe_ctx,
368 name,
369 nullptr, // Module *
370 m_options.num_instructions,
371 m_options.show_mixed ? m_options.num_lines_context : 0,
372 options,
373 result.GetOutputStream()))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000375 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 }
377 else
378 {
379 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
380 result.SetStatus (eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000381 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000382 }
Jim Ingham86511212010-06-15 18:47:14 +0000383 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000385 std::vector<AddressRange> ranges;
Greg Clayton32e0a752011-03-30 18:16:51 +0000386 AddressRange range;
Jason Molendab57e4a12013-11-04 09:33:30 +0000387 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Clayton32e0a752011-03-30 18:16:51 +0000388 if (m_options.frame_line)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000389 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000390 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000391 {
392 result.AppendError ("Cannot disassemble around the current line without a selected frame.\n");
393 result.SetStatus (eReturnStatusFailed);
394 return false;
395 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000396 LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
Greg Clayton32e0a752011-03-30 18:16:51 +0000397 if (pc_line_entry.IsValid())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000398 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000399 range = pc_line_entry.range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000400 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000401 else
Jim Ingham37023b02011-03-22 01:48:42 +0000402 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000403 m_options.at_pc = true; // No line entry, so just disassemble around the current pc
404 m_options.show_mixed = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000405 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000406 }
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000407 else if (m_options.current_function)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000408 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000409 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000410 {
411 result.AppendError ("Cannot disassemble around the current function without a selected frame.\n");
412 result.SetStatus (eReturnStatusFailed);
413 return false;
414 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000415 Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000416 if (symbol)
Greg Claytone7612132012-03-07 21:03:09 +0000417 {
418 range.GetBaseAddress() = symbol->GetAddress();
419 range.SetByteSize(symbol->GetByteSize());
420 }
Jim Ingham3555b5d2011-09-01 01:11:04 +0000421 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000422
423 // Did the "m_options.frame_line" find a valid range already? If so
424 // skip the rest...
425 if (range.GetByteSize() == 0)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000426 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000427 if (m_options.at_pc)
Jim Ingham37023b02011-03-22 01:48:42 +0000428 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000429 if (frame == nullptr)
Jim Ingham37023b02011-03-22 01:48:42 +0000430 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000431 result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
432 result.SetStatus (eReturnStatusFailed);
433 return false;
434 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000435 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Greg Clayton32e0a752011-03-30 18:16:51 +0000436 if (m_options.num_instructions == 0)
437 {
438 // Disassembling at the PC always disassembles some number of instructions (not the whole function).
439 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
440 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000441 ranges.push_back(range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000442 }
443 else
444 {
445 range.GetBaseAddress().SetOffset (m_options.start_addr);
446 if (range.GetBaseAddress().IsValid())
447 {
448 if (m_options.end_addr != LLDB_INVALID_ADDRESS)
Jim Ingham37023b02011-03-22 01:48:42 +0000449 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000450 if (m_options.end_addr <= m_options.start_addr)
451 {
452 result.AppendErrorWithFormat ("End address before start address.\n");
453 result.SetStatus (eReturnStatusFailed);
454 return false;
455 }
456 range.SetByteSize (m_options.end_addr - m_options.start_addr);
Jim Ingham37023b02011-03-22 01:48:42 +0000457 }
Jim Ingham2f4693a2014-04-03 17:16:17 +0000458 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000459 }
Jason Molenda801237a2013-04-11 03:14:01 +0000460 else
461 {
462 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS
Jim Ingham2f2c8762014-03-25 00:15:47 +0000463 && target)
Jason Molenda801237a2013-04-11 03:14:01 +0000464 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000465 if (!target->GetSectionLoadList().IsEmpty())
Jason Molenda801237a2013-04-11 03:14:01 +0000466 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000467 bool failed = false;
468 Address symbol_containing_address;
469 if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
Jason Molenda801237a2013-04-11 03:14:01 +0000470 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000471 ModuleSP module_sp (symbol_containing_address.GetModule());
472 SymbolContext sc;
473 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
474 module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
475 resolve_tail_call_address);
476 if (sc.function || sc.symbol)
477 {
478 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
479 }
480 else
481 {
482 failed = true;
483 }
Jason Molenda801237a2013-04-11 03:14:01 +0000484 }
485 else
486 {
487 failed = true;
488 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000489 if (failed)
490 {
491 result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
492 result.SetStatus (eReturnStatusFailed);
493 return false;
494 }
495 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000496 }
497 else
498 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000499 for (lldb::ModuleSP module_sp : target->GetImages().Modules())
500 {
501 lldb::addr_t file_addr = m_options.symbol_containing_addr;
502 Address file_address;
503 if (module_sp->ResolveFileAddress(file_addr, file_address))
504 {
505 SymbolContext sc;
506 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
507 module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address);
508 if (sc.function || sc.symbol)
509 {
510 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
511 ranges.push_back(range);
512 }
513 }
514 }
Jason Molenda801237a2013-04-11 03:14:01 +0000515 }
516 }
517 }
Jim Ingham37023b02011-03-22 01:48:42 +0000518 }
519 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000520 else
521 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000522
Jim Ingham37023b02011-03-22 01:48:42 +0000523 if (m_options.num_instructions != 0)
524 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000525 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000526 {
527 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000528 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000529 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000530 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000531 if (sc.function)
Greg Clayton32e0a752011-03-30 18:16:51 +0000532 range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
Greg Claytone7612132012-03-07 21:03:09 +0000533 else if (sc.symbol && sc.symbol->ValueIsAddress())
534 range.GetBaseAddress() = sc.symbol->GetAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000535 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000536 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000537 }
538
Greg Clayton32e0a752011-03-30 18:16:51 +0000539 if (!range.GetBaseAddress().IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000540 {
541 result.AppendError ("invalid frame");
542 result.SetStatus (eReturnStatusFailed);
543 return false;
544 }
545 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000546
547 bool print_sc_header = ranges.size() > 1;
548 for (AddressRange cur_range : ranges)
Jim Ingham37023b02011-03-22 01:48:42 +0000549 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000550 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
551 m_options.arch,
552 plugin_name,
553 flavor_string,
554 m_exe_ctx,
555 cur_range.GetBaseAddress(),
556 m_options.num_instructions,
557 m_options.show_mixed ? m_options.num_lines_context : 0,
558 options,
559 result.GetOutputStream()))
560 {
561 result.SetStatus (eReturnStatusSuccessFinishResult);
562 }
563 else
564 {
565 if (m_options.start_addr != LLDB_INVALID_ADDRESS)
566 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
567 else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
568 result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr);
569 result.SetStatus (eReturnStatusFailed);
570 }
Jim Ingham37023b02011-03-22 01:48:42 +0000571 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000572 if (print_sc_header)
573 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000574 }
575 else
576 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000577 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000578 {
579 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000580 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000581 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000582 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000583 if (sc.function)
584 range = sc.function->GetAddressRange();
Greg Claytone7612132012-03-07 21:03:09 +0000585 else if (sc.symbol && sc.symbol->ValueIsAddress())
586 {
587 range.GetBaseAddress() = sc.symbol->GetAddress();
588 range.SetByteSize (sc.symbol->GetByteSize());
589 }
Jim Ingham37023b02011-03-22 01:48:42 +0000590 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000591 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000592 }
593 else
594 {
595 result.AppendError ("invalid frame");
596 result.SetStatus (eReturnStatusFailed);
597 return false;
598 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000599 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000600 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000601
602 bool print_sc_header = ranges.size() > 1;
603 for (AddressRange cur_range : ranges)
604 {
605 if (cur_range.GetByteSize() == 0)
606 cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
Jim Ingham37023b02011-03-22 01:48:42 +0000607
Jim Ingham2f2c8762014-03-25 00:15:47 +0000608 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
609 m_options.arch,
610 plugin_name,
611 flavor_string,
612 m_exe_ctx,
613 cur_range,
614 m_options.num_instructions,
615 m_options.show_mixed ? m_options.num_lines_context : 0,
616 options,
617 result.GetOutputStream()))
618 {
619 result.SetStatus (eReturnStatusSuccessFinishResult);
620 }
621 else
622 {
623 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
624 result.SetStatus (eReturnStatusFailed);
625 }
626 if (print_sc_header)
627 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000628 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000629 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000630 }
631
Jim Ingham86511212010-06-15 18:47:14 +0000632 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000633}