summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands/CommandObjectImage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands/CommandObjectImage.cpp')
-rw-r--r--lldb/source/Commands/CommandObjectImage.cpp1419
1 files changed, 1419 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectImage.cpp b/lldb/source/Commands/CommandObjectImage.cpp
new file mode 100644
index 00000000000..ab728e9d32d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectImage.cpp
@@ -0,0 +1,1419 @@
+//===-- CommandObjectImage.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectImage.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Static Helper functions
+//----------------------------------------------------------------------
+static void
+DumpModuleArchitecture (Stream &strm, Module *module, uint32_t width)
+{
+ if (module)
+ {
+ if (width)
+ strm.Printf("%-*s", width, module->GetArchitecture().AsCString());
+ else
+ strm.PutCString(module->GetArchitecture().AsCString());
+ }
+}
+
+static void
+DumpModuleUUID (Stream &strm, Module *module)
+{
+ module->GetUUID().Dump (&strm);
+}
+
+static uint32_t
+DumpCompileUnitLineTable
+(
+ CommandContext *context,
+ Stream &strm,
+ Module *module,
+ const FileSpec &file_spec,
+ bool load_addresses
+)
+{
+ uint32_t num_matches = 0;
+ if (module)
+ {
+ SymbolContextList sc_list;
+ num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
+ 0,
+ false,
+ eSymbolContextCompUnit,
+ sc_list);
+
+ for (uint32_t i=0; i<num_matches; ++i)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ if (i > 0)
+ strm << "\n\n";
+
+ strm << "Line table for " << *dynamic_cast<FileSpec*> (sc.comp_unit) << " in `"
+ << module->GetFileSpec().GetFilename() << "\n";
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+ if (line_table)
+ line_table->GetDescription (&strm, context->GetExecutionContext().process, lldb::eDescriptionLevelBrief);
+ else
+ strm << "No line table";
+ }
+ }
+ }
+ return num_matches;
+}
+
+static void
+DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ {
+ char fullpath[PATH_MAX];
+ if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
+ {
+ strm.Printf("%-*s", width, fullpath);
+ return;
+ }
+ }
+ else
+ {
+ file_spec_ptr->Dump(&strm);
+ return;
+ }
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
+ else
+ file_spec_ptr->GetDirectory().Dump(&strm);
+ return;
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
+ else
+ file_spec_ptr->GetFilename().Dump(&strm);
+ return;
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+
+static void
+DumpModuleSymtab (CommandContext *context, Stream &strm, Module *module)
+{
+ if (module)
+ {
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ symtab->Dump(&strm, context->GetExecutionContext().process);
+ }
+ }
+}
+
+static void
+DumpModuleSections (CommandContext *context, Stream &strm, Module *module)
+{
+ if (module)
+ {
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ SectionList *section_list = objfile->GetSectionList();
+ if (section_list)
+ section_list->Dump(&strm, context->GetExecutionContext().process, true);
+ }
+ }
+}
+
+static bool
+DumpModuleSymbolVendor (Stream &strm, Module *module)
+{
+ if (module)
+ {
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
+ if (symbol_vendor)
+ {
+ symbol_vendor->Dump(&strm);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+LookupAddressInModule (CommandContext *context, Stream &strm, Module *module, uint32_t resolve_mask, lldb::addr_t raw_addr, lldb::addr_t offset)
+{
+ if (module)
+ {
+ lldb::addr_t addr = raw_addr - offset;
+ Address so_addr;
+ SymbolContext sc;
+ Process *process = context->GetExecutionContext().process;
+ if (process && process->IsAlive())
+ {
+ if (!process->ResolveLoadAddress (addr, so_addr))
+ return false;
+ else if (so_addr.GetModule() != module)
+ return false;
+ }
+ else
+ {
+ if (!module->ResolveFileAddress (addr, so_addr))
+ return false;
+ }
+
+ // If an offset was given, print out the address we ended up looking up
+ if (offset)
+ strm.Printf("0x%llx: ", addr);
+
+ ExecutionContextScope *exe_scope = context->GetExecutionContext().GetBestExecutionContextScope();
+ if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset))
+ strm.PutCString(": ");
+ so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
+ return true;
+ }
+
+ return false;
+}
+
+static uint32_t
+LookupSymbolInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+ if (module)
+ {
+ SymbolContext sc;
+
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ {
+ uint32_t i;
+ std::vector<uint32_t> match_indexes;
+ ConstString symbol_name (name);
+ uint32_t num_matches = 0;
+ if (name_is_regex)
+ {
+ RegularExpression name_regexp(name);
+ num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, eSymbolTypeAny,
+ match_indexes);
+ }
+ else
+ {
+ num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
+ }
+
+
+ if (num_matches > 0)
+ {
+ strm.Indent ();
+ strm.Printf("%u symbols match %s'%s' in ", num_matches,
+ name_is_regex ? "the regular expression " : "", name);
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ strm.IndentMore ();
+ Symtab::DumpSymbolHeader (&strm);
+ for (i=0; i < num_matches; ++i)
+ {
+ Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
+ strm.Indent ();
+ symbol->Dump (&strm, context->GetExecutionContext().process, i);
+ }
+ strm.IndentLess ();
+ return num_matches;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static void
+DumpSymbolContextList (CommandContext *context, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
+{
+ strm.IndentMore ();
+ uint32_t i;
+ const uint32_t num_matches = sc_list.GetSize();
+
+ for (i=0; i<num_matches; ++i)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ strm.Indent();
+ if (prepend_addr)
+ {
+ if (sc.line_entry.range.GetBaseAddress().IsValid())
+ {
+ lldb::addr_t vm_addr =
+ sc.line_entry.range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+ int addr_size = sizeof (addr_t);
+ Process *process = context->GetExecutionContext().process;
+ if (process)
+ addr_size = process->GetAddressByteSize();
+ if (vm_addr != LLDB_INVALID_ADDRESS)
+ strm.Address (vm_addr, addr_size);
+ else
+ sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);
+
+ strm.PutCString(" in ");
+ }
+ }
+ sc.DumpStopContext(&strm, context->GetExecutionContext().process, sc.line_entry.range.GetBaseAddress());
+ }
+ }
+ strm.IndentLess ();
+}
+
+static uint32_t
+LookupFunctionInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+ if (module && name && name[0])
+ {
+ SymbolContextList sc_list;
+
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+ if (symbol_vendor)
+ {
+ uint32_t num_matches = 0;
+ if (name_is_regex)
+ {
+ RegularExpression function_name_regex (name);
+ num_matches = symbol_vendor->FindFunctions(function_name_regex, true, sc_list);
+
+ }
+ else
+ {
+ ConstString function_name(name);
+ num_matches = symbol_vendor->FindFunctions(function_name, true, sc_list);
+ }
+
+ if (num_matches)
+ {
+ strm.Indent ();
+ strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ DumpSymbolContextList (context, strm, sc_list, true);
+ }
+ return num_matches;
+ }
+ }
+ return 0;
+}
+
+static uint32_t
+LookupFileAndLineInModule (CommandContext *context, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
+{
+ if (module && file_spec)
+ {
+ SymbolContextList sc_list;
+ const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
+ eSymbolContextEverything, sc_list);
+ if (num_matches > 0)
+ {
+ strm.Indent ();
+ strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ strm << file_spec;
+ if (line > 0)
+ strm.Printf (":%u", line);
+ strm << " in ";
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ DumpSymbolContextList (context, strm, sc_list, true);
+ return num_matches;
+ }
+ }
+ return 0;
+
+}
+
+
+//----------------------------------------------------------------------
+// Image symbol table dumping command
+//----------------------------------------------------------------------
+
+class CommandObjectImageDumpModuleList : public CommandObject
+{
+public:
+
+ CommandObjectImageDumpModuleList (const char *name,
+ const char *help,
+ const char *syntax) :
+ CommandObject (name, help, syntax)
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpModuleList ()
+ {
+ }
+
+ virtual int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches)
+ {
+ // Arguments are the standard module completer.
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eModuleCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ NULL,
+ matches);
+ return matches.GetSize();
+ }
+};
+
+class CommandObjectImageDumpSourceFileList : public CommandObject
+{
+public:
+
+ CommandObjectImageDumpSourceFileList (const char *name,
+ const char *help,
+ const char *syntax) :
+ CommandObject (name, help, syntax)
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSourceFileList ()
+ {
+ }
+
+ virtual int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches)
+ {
+ // Arguments are the standard source file completer.
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eSourceFileCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ NULL,
+ matches);
+ return matches.GetSize();
+ }
+};
+
+
+class CommandObjectImageDumpSymtab : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSymtab () :
+ CommandObjectImageDumpModuleList ("image dump symtab",
+ "Dump the symbol table from one or more executable images.",
+ "image dump symtab [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSymtab ()
+ {
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ num_dumped++;
+ DumpModuleSymtab (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module *image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ num_dumped++;
+ DumpModuleSymtab (context, result.GetOutputStream(), image_module);
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+
+};
+
+//----------------------------------------------------------------------
+// Image section dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSections : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSections () :
+ CommandObjectImageDumpModuleList (
+ "image dump sections",
+ "Dump the sections from one or more executable images.",
+ "image dump sections [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSections ()
+ {
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ num_dumped++;
+ DumpModuleSections (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ num_dumped++;
+ DumpModuleSections (context, result.GetOutputStream(), image_module);
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSymfile : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSymfile () :
+ CommandObjectImageDumpModuleList ("image dump symfile",
+ "Dump the debug symbol file for one or more executable images.",
+ "image dump symfile [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSymfile ()
+ {
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
+ num_dumped++;
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module))
+ num_dumped++;
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpLineTable : public CommandObjectImageDumpSourceFileList
+{
+public:
+ CommandObjectImageDumpLineTable () :
+ CommandObjectImageDumpSourceFileList ("image dump line-table",
+ "Dump the debug symbol file for one or more executable images.",
+ "image dump line-table <file1> [<file2> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpLineTable ()
+ {
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ uint32_t total_num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec file_spec(arg_cstr);
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ uint32_t num_dumped = 0;
+ for (uint32_t i = 0; i<num_modules; ++i)
+ {
+ if (DumpCompileUnitLineTable (context,
+ result.GetOutputStream(),
+ target->GetImages().GetModulePointerAtIndex(i),
+ file_spec,
+ exe_ctx.process != NULL && exe_ctx.process->IsAlive()))
+ num_dumped++;
+ }
+ if (num_dumped == 0)
+ result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
+ else
+ total_num_dumped += num_dumped;
+ }
+ }
+ }
+
+ if (total_num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no source filenames matched any command arguments");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Dump multi-word command
+//----------------------------------------------------------------------
+class CommandObjectImageDump : public CommandObjectMultiword
+{
+public:
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectImageDump(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("image dump",
+ "Dumps information in one or more executable images; 'line-table' expects a source file name",
+ "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
+ {
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymtab ()), "symtab", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSections ()), "sections", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymfile ()), "symfile", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpLineTable ()), "line-table", interpreter);
+ }
+
+ virtual
+ ~CommandObjectImageDump()
+ {
+ }
+};
+
+//----------------------------------------------------------------------
+// List images with associated information
+//----------------------------------------------------------------------
+class CommandObjectImageList : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options(),
+ m_format_array()
+ {
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ char short_option = (char) m_getopt_table[option_idx].val;
+ uint32_t width = 0;
+ if (option_arg)
+ width = strtoul (option_arg, NULL, 0);
+ m_format_array.push_back(std::make_pair(short_option, width));
+ Error error;
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_format_array.clear();
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
+ FormatWidthCollection m_format_array;
+ };
+
+ CommandObjectImageList () :
+ CommandObject (
+ "image list",
+ "List current executable and dependent shared library images.",
+ "image list [<cmd-options>]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageList ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ Stream &strm = result.GetOutputStream();
+
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
+ strm.Printf("[%3u] ", image_idx);
+
+ if (m_options.m_format_array.empty())
+ {
+ DumpFullpath(strm, &module->GetFileSpec(), 0);
+ }
+ else
+ {
+ const size_t num_entries = m_options.m_format_array.size();
+ for (size_t i=0; i<num_entries; ++i)
+ {
+ if (i > 0)
+ strm.PutChar(' ');
+ char format_char = m_options.m_format_array[i].first;
+ uint32_t width = m_options.m_format_array[i].second;
+ switch (format_char)
+ {
+ case 'a':
+ DumpModuleArchitecture (strm, module, width);
+ break;
+
+ case 'f':
+ DumpFullpath (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 'd':
+ DumpDirectory (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 'b':
+ DumpBasename (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 's':
+ case 'S':
+ {
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+ if (symbol_vendor)
+ {
+ SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
+ if (symbol_file)
+ {
+ if (format_char == 'S')
+ DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+ else
+ DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+ break;
+ }
+ }
+ strm.Printf("%.*s", width, "<NONE>");
+ }
+ break;
+
+ case 'u':
+ DumpModuleUUID(strm, module);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ strm.EOL();
+ }
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ return result.Succeeded();
+ }
+protected:
+
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageList::CommandOptions::g_option_table[] =
+{
+{ 0, false, "arch", 'a', optional_argument, NULL, 0, "<width>", "Display the architecture when listing images."},
+{ 0, false, "uuid", 'u', no_argument, NULL, 0, NULL, "Display the UUID when listing images."},
+{ 0, false, "fullpath", 'f', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image object file."},
+{ 0, false, "directory", 'd', optional_argument, NULL, 0, "<width>", "Display the directory with optional width for the image object file."},
+{ 0, false, "basename", 'b', optional_argument, NULL, 0, "<width>", "Display the basename with optional width for the image object file."},
+{ 0, false, "symfile", 's', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image symbol file with optional width."},
+{ 0, false, "symfile-basename", 'S', optional_argument, NULL, 0, "<width>", "Display the basename to the image symbol file with optional width."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//----------------------------------------------------------------------
+// Lookup information in images
+//----------------------------------------------------------------------
+class CommandObjectImageLookup : public CommandObject
+{
+public:
+
+ enum
+ {
+ eLookupTypeInvalid = -1,
+ eLookupTypeAddress = 0,
+ eLookupTypeSymbol,
+ eLookupTypeFileLine, // Line is optional
+ eLookupTypeFunction,
+ kNumLookupTypes
+ };
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ ResetOptionValues();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'a':
+ m_type = eLookupTypeAddress;
+ m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+ if (m_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
+ break;
+
+ case 'o':
+ m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+ if (m_offset == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg);
+ break;
+
+ case 's':
+ m_str = option_arg;
+ m_type = eLookupTypeSymbol;
+ break;
+
+ case 'f':
+ m_file.SetFile (option_arg);
+ m_type = eLookupTypeFileLine;
+ break;
+
+ case 'i':
+ m_check_inlines = false;
+ break;
+
+ case 'l':
+ m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
+ if (m_line_number == UINT32_MAX)
+ error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg);
+ else if (m_line_number == 0)
+ error.SetErrorString ("Zero is an invalid line number.");
+ m_type = eLookupTypeFileLine;
+ break;
+
+ case 'n':
+ m_str = option_arg;
+ m_type = eLookupTypeFunction;
+ break;
+
+ case 'r':
+ m_use_regex = true;
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_type = eLookupTypeInvalid;
+ m_str.clear();
+ m_file.Clear();
+ m_addr = LLDB_INVALID_ADDRESS;
+ m_offset = 0;
+ m_line_number = 0;
+ m_use_regex = false;
+ m_check_inlines = true;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ int m_type; // Should be a eLookupTypeXXX enum after parsing options
+ std::string m_str; // Holds name lookup
+ FileSpec m_file; // Files for file lookups
+ lldb::addr_t m_addr; // Holds the address to lookup
+ lldb::addr_t m_offset; // Subtract this offset from m_addr before doing lookups.
+ uint32_t m_line_number; // Line number for file+line lookups
+ bool m_use_regex; // Name lookups in m_str are regular expressions.
+ bool m_check_inlines;// Check for inline entries when looking up by file/line.
+ };
+
+ CommandObjectImageLookup () :
+ CommandObject (
+ "image lookup",
+ "Look up information within executable and dependent shared library images.",
+ "image lookup [<cmd-options>] [<file1>...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageLookup ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
+ bool
+ LookupInModule (CommandContext *context, Module *module, CommandReturnObject &result, bool &syntax_error)
+ {
+ switch (m_options.m_type)
+ {
+ case eLookupTypeAddress:
+ if (m_options.m_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (LookupAddressInModule (context, result.GetOutputStream(), module, eSymbolContextEverything, m_options.m_addr, m_options.m_offset))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeSymbol:
+ if (!m_options.m_str.empty())
+ {
+ if (LookupSymbolInModule (context, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeFileLine:
+ if (m_options.m_file)
+ {
+
+ if (LookupFileAndLineInModule (context,
+ result.GetOutputStream(),
+ module,
+ m_options.m_file,
+ m_options.m_line_number,
+ m_options.m_check_inlines))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeFunction:
+ if (!m_options.m_str.empty())
+ {
+ if (LookupFunctionInModule (context,
+ result.GetOutputStream(),
+ module,
+ m_options.m_str.c_str(),
+ m_options.m_use_regex))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+ syntax_error = true;
+ break;
+ }
+
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ virtual bool
+ 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;
+ }
+ else
+ {
+ bool syntax_error = false;
+ uint32_t i;
+ uint32_t num_successful_lookups = 0;
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+ // Dump all sections for all modules images
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ for (i = 0; i<num_modules && syntax_error == false; ++i)
+ {
+ if (LookupInModule (context, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
+ {
+ result.GetOutputStream().EOL();
+ num_successful_lookups++;
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ if (LookupInModule (context, image_module, result, syntax_error))
+ {
+ result.GetOutputStream().EOL();
+ num_successful_lookups++;
+ }
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_successful_lookups > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+protected:
+
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageLookup::CommandOptions::g_option_table[] =
+{
+{ 1, true, "address", 'a', required_argument, NULL, 0, "<addr>", "Lookup an address in one or more executable images."},
+{ 1, false, "offset", 'o', required_argument, NULL, 0, "<offset>", "When looking up an address subtract <offset> from any addresses before doing the lookup."},
+{ 2, true, "symbol", 's', required_argument, NULL, 0, "<name>", "Lookup a symbol by name in the symbol tables in one or more executable images."},
+{ 2, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
+{ 3, true, "file", 'f', required_argument, NULL, 0, "<file>", "Lookup a file by fullpath or basename in one or more executable images."},
+{ 3, false, "line", 'l', required_argument, NULL, 0, "<line>", "Lookup a line number in a file (must be used in conjunction with --file)."},
+{ 3, false, "no-inlines", 'i', no_argument, NULL, 0, NULL, "Check inline line entries (must be used in conjunction with --file)."},
+{ 4, true, "function", 'n', required_argument, NULL, 0, "<name>", "Lookup a function by name in the debug symbols in one or more executable images."},
+{ 5, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+
+
+//----------------------------------------------------------------------
+// CommandObjectImage constructor
+//----------------------------------------------------------------------
+CommandObjectImage::CommandObjectImage(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("image",
+ "Access information for one or more executable images.",
+ "image [dump|list] ...")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDump (interpreter)), "dump", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageList ()), "list", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageLookup ()), "lookup", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectImage::~CommandObjectImage()
+{
+}
+
OpenPOWER on IntegriCloud