summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands/CommandObjectDisassemble.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
committerChris Lattner <sabre@nondot.org>2010-06-08 16:52:24 +0000
commit30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c (patch)
treef70013106f6a461a14abcd71c65f48a95a2979a6 /lldb/source/Commands/CommandObjectDisassemble.cpp
parent312c4c799da215b337f790fda330f70c4aa757cf (diff)
downloadbcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.tar.gz
bcm5719-llvm-30fdc8d841c9d24ac5f3d452b6ece84ee0ac991c.zip
Initial checkin of lldb code from internal Apple repo.
llvm-svn: 105619
Diffstat (limited to 'lldb/source/Commands/CommandObjectDisassemble.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
new file mode 100644
index 00000000000..0985504e4ff
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -0,0 +1,431 @@
+//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectDisassemble.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#define DEFAULT_DISASM_BYTE_SIZE 32
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectDisassemble::CommandOptions::CommandOptions () :
+ Options(),
+ m_func_name(),
+ m_load_addr()
+{
+ ResetOptionValues();
+}
+
+CommandObjectDisassemble::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'm':
+ show_mixed = true;
+ break;
+
+ case 'c':
+ num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
+ break;
+
+ case 'b':
+ show_bytes = true;
+ break;
+
+ case 'a':
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
+ break;
+
+ case 'n':
+ m_func_name = option_arg;
+ break;
+
+ case 'r':
+ raw = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ show_mixed = false;
+ show_bytes = false;
+ num_lines_context = 0;
+ m_func_name.clear();
+ m_load_addr = LLDB_INVALID_ADDRESS;
+}
+
+const lldb::OptionDefinition*
+CommandObjectDisassemble::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+lldb::OptionDefinition
+CommandObjectDisassemble::CommandOptions::g_option_table[] =
+{
+{ 0, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 0, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 0, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 0, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 1, false, "address", 'a', required_argument, NULL, 0, "<address>", "Address to start disassembling."},
+{ 1, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 1, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 1, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 1, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 2, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>", "Disassemble entire contents of the given function name."},
+{ 2, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 2, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 2, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 2, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectDisassemble
+//-------------------------------------------------------------------------
+
+CommandObjectDisassemble::CommandObjectDisassemble () :
+ CommandObject ("disassemble",
+ "Disassemble bytes in the current function or anywhere in the inferior program.",
+ "disassemble [[<start-addr> [<end-addr>]] | <function-name>] [<cmd-options>]")
+{
+}
+
+CommandObjectDisassemble::~CommandObjectDisassemble()
+{
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ const SymbolContextList &sc_list
+)
+{
+ const size_t count = sc_list.GetSize();
+ SymbolContext sc;
+ AddressRange range;
+ for (size_t i=0; i<count; ++i)
+ {
+ if (sc_list.GetContextAtIndex(i, sc) == false)
+ break;
+ if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
+ {
+ lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ lldb::addr_t end_addr = addr + range.GetByteSize();
+ Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+ }
+ }
+ }
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ lldb::addr_t addr,
+ lldb::addr_t end_addr
+)
+{
+ if (addr == LLDB_INVALID_ADDRESS)
+ return;
+
+ if (end_addr == LLDB_INVALID_ADDRESS || addr >= end_addr)
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+
+ ExecutionContext exe_ctx (context->GetExecutionContext());
+ DataExtractor data;
+ size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, end_addr - addr, data);
+ if (bytes_disassembled == 0)
+ {
+ // Nothing got disassembled...
+ }
+ else
+ {
+ // We got some things disassembled...
+ size_t num_instructions = disassembler->GetInstructionList().GetSize();
+ uint32_t offset = 0;
+ Stream &output_stream = result.GetOutputStream();
+ SymbolContext sc;
+ SymbolContext prev_sc;
+ AddressRange sc_range;
+ if (m_options.show_mixed)
+ output_stream.IndentMore ();
+
+ for (size_t i=0; i<num_instructions; ++i)
+ {
+ Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+ if (inst)
+ {
+ lldb::addr_t curr_addr = addr + offset;
+ if (m_options.show_mixed)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (!sc_range.ContainsLoadAddress (curr_addr, process))
+ {
+ prev_sc = sc;
+ Address curr_so_addr;
+ if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
+ {
+ if (curr_so_addr.GetSection())
+ {
+ Module *module = curr_so_addr.GetSection()->GetModule();
+ uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
+ if (resolved_mask)
+ {
+ sc.GetAddressRange (eSymbolContextEverything, sc_range);
+ if (sc != prev_sc)
+ {
+ if (offset != 0)
+ output_stream.EOL();
+
+ sc.DumpStopContext(&output_stream, process, curr_so_addr);
+ output_stream.EOL();
+ if (sc.comp_unit && sc.line_entry.IsValid())
+ {
+ interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers (
+ sc.line_entry.file,
+ sc.line_entry.line,
+ m_options.num_lines_context,
+ m_options.num_lines_context,
+ m_options.num_lines_context ? "->" : "",
+ &output_stream);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (m_options.show_mixed)
+ output_stream.IndentMore ();
+ output_stream.Indent();
+ size_t inst_byte_size = inst->GetByteSize();
+ inst->Dump(&output_stream, curr_addr, m_options.show_bytes ? &data : NULL, offset, exe_ctx, m_options.raw);
+ output_stream.EOL();
+ offset += inst_byte_size;
+ if (m_options.show_mixed)
+ output_stream.IndentLess ();
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (m_options.show_mixed)
+ output_stream.IndentLess ();
+
+ }
+}
+
+bool
+CommandObjectDisassemble::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ArchSpec arch(target->GetArchitecture());
+ if (!arch.IsValid())
+ {
+ result.AppendError ("target needs valid architecure in order to be able to disassemble");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Disassembler *disassembler = Disassembler::FindPlugin(arch);
+
+ if (disassembler == NULL)
+ {
+ result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
+ ConstString name;
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0 && m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ addr = m_options.m_load_addr;
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ } else if (argc == 0 && !m_options.m_func_name.empty())
+ {
+ ConstString tmpname(m_options.m_func_name.c_str());
+ name = tmpname;
+ } else if (argc == 0)
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.frame)
+ {
+ SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function)
+ {
+ addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ end_addr = addr + sc.function->GetAddressRange().GetByteSize();
+ }
+ else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ {
+ addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ end_addr = addr + sc.symbol->GetAddressRangePtr()->GetByteSize();
+ if (addr == end_addr)
+ end_addr += DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else
+ {
+ addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid frame");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else if (argc == 1)
+ {
+ const char *arg = command.GetArgumentAtIndex(0);
+ addr = Args::StringToAddress (arg);
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ // Lookup function or symbol name?
+ ConstString tmpname(arg);
+ name = tmpname;
+ }
+ else
+ {
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else if (argc >= 1 && argc <= 2)
+ {
+ addr = Args::StringToAddress (command.GetArgumentAtIndex(0));
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ end_addr = Args::StringToAddress (command.GetArgumentAtIndex(1), addr);
+ if (end_addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(1));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (!name.IsEmpty())
+ {
+ SymbolContextList sc_list;
+
+ if (target->GetImages().FindFunctions(name, sc_list))
+ {
+ Disassemble (context, interpreter, result, disassembler, sc_list);
+ }
+ else if (target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
+ {
+ Disassemble (context, interpreter, result, disassembler, sc_list);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (addr < end_addr)
+ {
+ Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+ }
+
+ if (addr == LLDB_INVALID_ADDRESS && name.IsEmpty())
+ {
+ result.AppendError ("No recognizable address of function name provided");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ {
+ return result.Succeeded();
+ }
+}
OpenPOWER on IntegriCloud