blob: 6f5287626f50a21cf9079b834993e3eaa5d8e805 [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{
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000246{ LLDB_OPT_SET_ALL, false, "bytes" , 'b', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling."},
247{ LLDB_OPT_SET_ALL, false, "context" , 'C', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show."},
248{ LLDB_OPT_SET_ALL, false, "mixed" , 'm', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display."},
249{ LLDB_OPT_SET_ALL, false, "raw" , 'r', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information."},
250{ LLDB_OPT_SET_ALL, false, "plugin" , 'P', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use."},
251{ 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 +0000252 "Currently the only valid options are default, and for Intel"
253 " architectures, att and intel."},
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000254{ 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 +0000255{ LLDB_OPT_SET_1 |
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000256 LLDB_OPT_SET_2 , true , "start-address", 's', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression,"Address at which to start disassembling."},
257{ 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 +0000258{ LLDB_OPT_SET_2 |
259 LLDB_OPT_SET_3 |
260 LLDB_OPT_SET_4 |
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000261 LLDB_OPT_SET_5 , false, "count" , 'c', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display."},
262{ LLDB_OPT_SET_3 , false, "name" , 'n', OptionParser::eRequiredArgument , nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName,
Zachary Turnerd37221d2014-07-09 16:31:49 +0000263 "Disassemble entire contents of the given function name."},
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000264{ 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 table information, else disassemble around the pc."},
267{ LLDB_OPT_SET_7 , false, "address" , 'a', OptionParser::eRequiredArgument , nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address."},
268{ 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269};
270
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000271//-------------------------------------------------------------------------
272// CommandObjectDisassemble
273//-------------------------------------------------------------------------
274
Kate Stone7428a182016-07-14 22:03:10 +0000275CommandObjectDisassemble::CommandObjectDisassemble(CommandInterpreter &interpreter)
276 : CommandObjectParsed(interpreter, "disassemble", "Disassemble specified instructions in the current target. "
277 "Defaults to the current function for the current thread and "
278 "stack frame.",
279 "disassemble [<cmd-options>]"),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000280 m_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000281{
282}
283
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000284CommandObjectDisassemble::~CommandObjectDisassemble() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000285
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000286bool
Jim Ingham5a988412012-06-08 21:56:10 +0000287CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000288{
Greg Claytona7015092010-09-18 01:14:36 +0000289 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000290 if (target == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000291 {
Greg Claytoneffe5c92011-05-03 22:09:39 +0000292 result.AppendError ("invalid target, create a debug target using the 'target create' command");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 result.SetStatus (eReturnStatusFailed);
294 return false;
295 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000296 if (!m_options.arch.IsValid())
297 m_options.arch = target->GetArchitecture();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298
Greg Clayton32e0a752011-03-30 18:16:51 +0000299 if (!m_options.arch.IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300 {
Jason Molenda125adcf02015-09-04 03:40:29 +0000301 result.AppendError ("use the --arch option or set the target architecture to disassemble");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000302 result.SetStatus (eReturnStatusFailed);
303 return false;
304 }
305
Greg Clayton1080edbc2011-03-25 18:03:16 +0000306 const char *plugin_name = m_options.GetPluginName ();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000307 const char *flavor_string = m_options.GetFlavorString();
308
309 DisassemblerSP disassembler = Disassembler::FindPlugin(m_options.arch, flavor_string, plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310
Sean Callanan9a028512012-08-09 00:50:26 +0000311 if (!disassembler)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000313 if (plugin_name)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000314 {
315 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in named '%s' that supports the '%s' architecture.\n",
Greg Clayton357132e2011-03-26 19:14:58 +0000316 plugin_name,
Greg Clayton32e0a752011-03-30 18:16:51 +0000317 m_options.arch.GetArchitectureName());
Jim Ingham0f063ba2013-03-02 00:26:47 +0000318 }
Greg Clayton1080edbc2011-03-25 18:03:16 +0000319 else
Greg Clayton357132e2011-03-26 19:14:58 +0000320 result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for the '%s' architecture.\n",
Greg Clayton32e0a752011-03-30 18:16:51 +0000321 m_options.arch.GetArchitectureName());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000322 result.SetStatus (eReturnStatusFailed);
323 return false;
324 }
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000325 else if (flavor_string != nullptr && !disassembler->FlavorValidForArchSpec(m_options.arch, flavor_string))
Jim Ingham0f063ba2013-03-02 00:26:47 +0000326 result.AppendWarningWithFormat("invalid disassembler flavor \"%s\", using default.\n", flavor_string);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000327
328 result.SetStatus (eReturnStatusSuccessFinishResult);
329
Greg Claytondda4f7b2010-06-30 23:03:03 +0000330 if (command.GetArgumentCount() != 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000331 {
Greg Claytona7015092010-09-18 01:14:36 +0000332 result.AppendErrorWithFormat ("\"disassemble\" arguments are specified as options.\n");
Todd Fialae1cfbc72016-08-11 23:51:28 +0000333 const int terminal_width =
334 GetCommandInterpreter().GetDebugger().GetTerminalWidth();
335 GetOptions()->GenerateOptionUsage(result.GetErrorStream(), this,
336 terminal_width);
Jim Ingham86511212010-06-15 18:47:14 +0000337 result.SetStatus (eReturnStatusFailed);
338 return false;
339 }
Jim Ingham37023b02011-03-22 01:48:42 +0000340
Greg Claytondda4f7b2010-06-30 23:03:03 +0000341 if (m_options.show_mixed && m_options.num_lines_context == 0)
Greg Clayton6dbd3982010-09-15 05:51:24 +0000342 m_options.num_lines_context = 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000343
Greg Claytonb10d72f2011-06-28 19:01:40 +0000344 // Always show the PC in the disassembly
345 uint32_t options = Disassembler::eOptionMarkPCAddress;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000346
Greg Claytonb10d72f2011-06-28 19:01:40 +0000347 // Mark the source line for the current PC only if we are doing mixed source and assembly
348 if (m_options.show_mixed)
349 options |= Disassembler::eOptionMarkPCSourceLine;
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000350
351 if (m_options.show_bytes)
352 options |= Disassembler::eOptionShowBytes;
353
354 if (m_options.raw)
355 options |= Disassembler::eOptionRawOuput;
Jim Ingham37023b02011-03-22 01:48:42 +0000356
Greg Clayton32e0a752011-03-30 18:16:51 +0000357 if (!m_options.func_name.empty())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000358 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000359 ConstString name(m_options.func_name.c_str());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000360
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000361 if (Disassembler::Disassemble(m_interpreter.GetDebugger(),
362 m_options.arch,
363 plugin_name,
364 flavor_string,
365 m_exe_ctx,
366 name,
367 nullptr, // Module *
368 m_options.num_instructions,
369 m_options.show_mixed ? m_options.num_lines_context : 0,
370 options,
371 result.GetOutputStream()))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000372 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000373 result.SetStatus (eReturnStatusSuccessFinishResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000374 }
375 else
376 {
377 result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
378 result.SetStatus (eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000379 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000380 }
Jim Ingham86511212010-06-15 18:47:14 +0000381 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000382 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000383 std::vector<AddressRange> ranges;
Greg Clayton32e0a752011-03-30 18:16:51 +0000384 AddressRange range;
Jason Molendab57e4a12013-11-04 09:33:30 +0000385 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Clayton32e0a752011-03-30 18:16:51 +0000386 if (m_options.frame_line)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000387 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000388 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000389 {
390 result.AppendError ("Cannot disassemble around the current line without a selected frame.\n");
391 result.SetStatus (eReturnStatusFailed);
392 return false;
393 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000394 LineEntry pc_line_entry (frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
Greg Clayton32e0a752011-03-30 18:16:51 +0000395 if (pc_line_entry.IsValid())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000396 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000397 range = pc_line_entry.range;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000398 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000399 else
Jim Ingham37023b02011-03-22 01:48:42 +0000400 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000401 m_options.at_pc = true; // No line entry, so just disassemble around the current pc
402 m_options.show_mixed = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000403 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000404 }
Greg Clayton1fb2e7d2012-12-14 22:36:35 +0000405 else if (m_options.current_function)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000406 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000407 if (frame == nullptr)
Jim Ingham3555b5d2011-09-01 01:11:04 +0000408 {
409 result.AppendError ("Cannot disassemble around the current function without a selected frame.\n");
410 result.SetStatus (eReturnStatusFailed);
411 return false;
412 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000413 Symbol *symbol = frame->GetSymbolContext(eSymbolContextSymbol).symbol;
Jim Ingham3555b5d2011-09-01 01:11:04 +0000414 if (symbol)
Greg Claytone7612132012-03-07 21:03:09 +0000415 {
416 range.GetBaseAddress() = symbol->GetAddress();
417 range.SetByteSize(symbol->GetByteSize());
418 }
Jim Ingham3555b5d2011-09-01 01:11:04 +0000419 }
Greg Clayton32e0a752011-03-30 18:16:51 +0000420
421 // Did the "m_options.frame_line" find a valid range already? If so
422 // skip the rest...
423 if (range.GetByteSize() == 0)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000424 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000425 if (m_options.at_pc)
Jim Ingham37023b02011-03-22 01:48:42 +0000426 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000427 if (frame == nullptr)
Jim Ingham37023b02011-03-22 01:48:42 +0000428 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000429 result.AppendError ("Cannot disassemble around the current PC without a selected frame.\n");
430 result.SetStatus (eReturnStatusFailed);
431 return false;
432 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000433 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Greg Clayton32e0a752011-03-30 18:16:51 +0000434 if (m_options.num_instructions == 0)
435 {
436 // Disassembling at the PC always disassembles some number of instructions (not the whole function).
437 m_options.num_instructions = DEFAULT_DISASM_NUM_INS;
438 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000439 ranges.push_back(range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000440 }
441 else
442 {
443 range.GetBaseAddress().SetOffset (m_options.start_addr);
444 if (range.GetBaseAddress().IsValid())
445 {
446 if (m_options.end_addr != LLDB_INVALID_ADDRESS)
Jim Ingham37023b02011-03-22 01:48:42 +0000447 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000448 if (m_options.end_addr <= m_options.start_addr)
449 {
450 result.AppendErrorWithFormat ("End address before start address.\n");
451 result.SetStatus (eReturnStatusFailed);
452 return false;
453 }
454 range.SetByteSize (m_options.end_addr - m_options.start_addr);
Jim Ingham37023b02011-03-22 01:48:42 +0000455 }
Jim Ingham2f4693a2014-04-03 17:16:17 +0000456 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000457 }
Jason Molenda801237a2013-04-11 03:14:01 +0000458 else
459 {
460 if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS
Jim Ingham2f2c8762014-03-25 00:15:47 +0000461 && target)
Jason Molenda801237a2013-04-11 03:14:01 +0000462 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000463 if (!target->GetSectionLoadList().IsEmpty())
Jason Molenda801237a2013-04-11 03:14:01 +0000464 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000465 bool failed = false;
466 Address symbol_containing_address;
467 if (target->GetSectionLoadList().ResolveLoadAddress (m_options.symbol_containing_addr, symbol_containing_address))
Jason Molenda801237a2013-04-11 03:14:01 +0000468 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000469 ModuleSP module_sp (symbol_containing_address.GetModule());
470 SymbolContext sc;
471 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
472 module_sp->ResolveSymbolContextForAddress (symbol_containing_address, eSymbolContextEverything, sc,
473 resolve_tail_call_address);
474 if (sc.function || sc.symbol)
475 {
476 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
477 }
478 else
479 {
480 failed = true;
481 }
Jason Molenda801237a2013-04-11 03:14:01 +0000482 }
483 else
484 {
485 failed = true;
486 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000487 if (failed)
488 {
489 result.AppendErrorWithFormat ("Could not find function bounds for address 0x%" PRIx64 "\n", m_options.symbol_containing_addr);
490 result.SetStatus (eReturnStatusFailed);
491 return false;
492 }
493 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000494 }
495 else
496 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000497 for (lldb::ModuleSP module_sp : target->GetImages().Modules())
498 {
499 lldb::addr_t file_addr = m_options.symbol_containing_addr;
500 Address file_address;
501 if (module_sp->ResolveFileAddress(file_addr, file_address))
502 {
503 SymbolContext sc;
504 bool resolve_tail_call_address = true; // PC can be one past the address range of the function.
505 module_sp->ResolveSymbolContextForAddress (file_address, eSymbolContextEverything, sc, resolve_tail_call_address);
506 if (sc.function || sc.symbol)
507 {
508 sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, range);
509 ranges.push_back(range);
510 }
511 }
512 }
Jason Molenda801237a2013-04-11 03:14:01 +0000513 }
514 }
515 }
Jim Ingham37023b02011-03-22 01:48:42 +0000516 }
517 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000518 else
519 ranges.push_back(range);
Jason Molenda801237a2013-04-11 03:14:01 +0000520
Jim Ingham37023b02011-03-22 01:48:42 +0000521 if (m_options.num_instructions != 0)
522 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000523 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000524 {
525 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000526 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000527 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000528 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000529 if (sc.function)
Greg Clayton32e0a752011-03-30 18:16:51 +0000530 range.GetBaseAddress() = sc.function->GetAddressRange().GetBaseAddress();
Greg Claytone7612132012-03-07 21:03:09 +0000531 else if (sc.symbol && sc.symbol->ValueIsAddress())
532 range.GetBaseAddress() = sc.symbol->GetAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000533 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000534 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000535 }
536
Greg Clayton32e0a752011-03-30 18:16:51 +0000537 if (!range.GetBaseAddress().IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000538 {
539 result.AppendError ("invalid frame");
540 result.SetStatus (eReturnStatusFailed);
541 return false;
542 }
543 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000544
545 bool print_sc_header = ranges.size() > 1;
546 for (AddressRange cur_range : ranges)
Jim Ingham37023b02011-03-22 01:48:42 +0000547 {
Jim Ingham2f2c8762014-03-25 00:15:47 +0000548 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
549 m_options.arch,
550 plugin_name,
551 flavor_string,
552 m_exe_ctx,
553 cur_range.GetBaseAddress(),
554 m_options.num_instructions,
555 m_options.show_mixed ? m_options.num_lines_context : 0,
556 options,
557 result.GetOutputStream()))
558 {
559 result.SetStatus (eReturnStatusSuccessFinishResult);
560 }
561 else
562 {
563 if (m_options.start_addr != LLDB_INVALID_ADDRESS)
564 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
565 else if (m_options.symbol_containing_addr != LLDB_INVALID_ADDRESS)
566 result.AppendErrorWithFormat ("Failed to disassemble memory in function at 0x%8.8" PRIx64 ".\n", m_options.symbol_containing_addr);
567 result.SetStatus (eReturnStatusFailed);
568 }
Jim Ingham37023b02011-03-22 01:48:42 +0000569 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000570 if (print_sc_header)
571 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000572 }
573 else
574 {
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000575 if (ranges.empty())
Jim Ingham37023b02011-03-22 01:48:42 +0000576 {
577 // The default action is to disassemble the current frame function.
Greg Claytonc14ee322011-09-22 04:58:26 +0000578 if (frame)
Jim Ingham37023b02011-03-22 01:48:42 +0000579 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000580 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Jim Ingham37023b02011-03-22 01:48:42 +0000581 if (sc.function)
582 range = sc.function->GetAddressRange();
Greg Claytone7612132012-03-07 21:03:09 +0000583 else if (sc.symbol && sc.symbol->ValueIsAddress())
584 {
585 range.GetBaseAddress() = sc.symbol->GetAddress();
586 range.SetByteSize (sc.symbol->GetByteSize());
587 }
Jim Ingham37023b02011-03-22 01:48:42 +0000588 else
Greg Claytonc14ee322011-09-22 04:58:26 +0000589 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000590 }
591 else
592 {
593 result.AppendError ("invalid frame");
594 result.SetStatus (eReturnStatusFailed);
595 return false;
596 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000597 ranges.push_back(range);
Jim Ingham37023b02011-03-22 01:48:42 +0000598 }
Jim Ingham2f2c8762014-03-25 00:15:47 +0000599
600 bool print_sc_header = ranges.size() > 1;
601 for (AddressRange cur_range : ranges)
602 {
603 if (cur_range.GetByteSize() == 0)
604 cur_range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE);
Jim Ingham37023b02011-03-22 01:48:42 +0000605
Jim Ingham2f2c8762014-03-25 00:15:47 +0000606 if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
607 m_options.arch,
608 plugin_name,
609 flavor_string,
610 m_exe_ctx,
611 cur_range,
612 m_options.num_instructions,
613 m_options.show_mixed ? m_options.num_lines_context : 0,
614 options,
615 result.GetOutputStream()))
616 {
617 result.SetStatus (eReturnStatusSuccessFinishResult);
618 }
619 else
620 {
621 result.AppendErrorWithFormat ("Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", m_options.start_addr);
622 result.SetStatus (eReturnStatusFailed);
623 }
624 if (print_sc_header)
625 result.AppendMessage("\n");
Jim Ingham37023b02011-03-22 01:48:42 +0000626 }
Greg Claytondda4f7b2010-06-30 23:03:03 +0000627 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000628 }
629
Jim Ingham86511212010-06-15 18:47:14 +0000630 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631}