| //===-- 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/Debugger.h" |
| #include "lldb/Core/FileSpec.h" |
| #include "lldb/Core/Module.h" |
| #include "lldb/Core/RegularExpression.h" |
| #include "lldb/Core/Stream.h" |
| #include "lldb/Interpreter/Args.h" |
| #include "lldb/Interpreter/Options.h" |
| #include "lldb/Interpreter/CommandCompletions.h" |
| #include "lldb/Interpreter/CommandInterpreter.h" |
| #include "lldb/Interpreter/CommandReturnObject.h" |
| #include "lldb/Symbol/LineTable.h" |
| #include "lldb/Symbol/ObjectFile.h" |
| #include "lldb/Symbol/SymbolFile.h" |
| #include "lldb/Symbol/SymbolVendor.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Target/Target.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 |
| ( |
| CommandInterpreter &interpreter, |
| 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, |
| interpreter.GetDebugger().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 (CommandInterpreter &interpreter, Stream &strm, Module *module) |
| { |
| if (module) |
| { |
| ObjectFile *objfile = module->GetObjectFile (); |
| if (objfile) |
| { |
| Symtab *symtab = objfile->GetSymtab(); |
| if (symtab) |
| symtab->Dump(&strm, interpreter.GetDebugger().GetExecutionContext().process); |
| } |
| } |
| } |
| |
| static void |
| DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *module) |
| { |
| if (module) |
| { |
| ObjectFile *objfile = module->GetObjectFile (); |
| if (objfile) |
| { |
| SectionList *section_list = objfile->GetSectionList(); |
| if (section_list) |
| section_list->Dump(&strm, interpreter.GetDebugger().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 |
| ( |
| CommandInterpreter &interpreter, |
| Stream &strm, |
| Module *module, |
| uint32_t resolve_mask, |
| lldb::addr_t raw_addr, |
| lldb::addr_t offset, |
| bool verbose |
| ) |
| { |
| if (module) |
| { |
| lldb::addr_t addr = raw_addr - offset; |
| Address so_addr; |
| SymbolContext sc; |
| Process *process = interpreter.GetDebugger().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 = interpreter.GetDebugger().GetExecutionContext().GetBestExecutionContextScope(); |
| strm.IndentMore(); |
| strm.Indent (" Address: "); |
| so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset); |
| strm.EOL(); |
| strm.Indent (" Summary: "); |
| so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription); |
| strm.EOL(); |
| // Print out detailed address information when verbose is enabled |
| if (verbose) |
| { |
| if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext)) |
| strm.EOL(); |
| } |
| strm.IndentLess(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static uint32_t |
| LookupSymbolInModule (CommandInterpreter &interpreter, 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, interpreter.GetDebugger().GetExecutionContext().process, i); |
| } |
| strm.IndentLess (); |
| return num_matches; |
| } |
| } |
| } |
| } |
| return 0; |
| } |
| |
| |
| static void |
| DumpSymbolContextList (CommandInterpreter &interpreter, 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(interpreter.GetDebugger().GetExecutionContext().process); |
| int addr_size = sizeof (addr_t); |
| Process *process = interpreter.GetDebugger().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, interpreter.GetDebugger().GetExecutionContext().process, sc.line_entry.range.GetBaseAddress(), true, false); |
| } |
| } |
| strm.IndentLess (); |
| } |
| |
| static uint32_t |
| LookupFunctionInModule (CommandInterpreter &interpreter, 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, eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector, 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 (interpreter, strm, sc_list, true); |
| } |
| return num_matches; |
| } |
| } |
| return 0; |
| } |
| |
| static uint32_t |
| LookupTypeInModule |
| ( |
| CommandInterpreter &interpreter, |
| Stream &strm, |
| Module *module, |
| const char *name_cstr, |
| bool name_is_regex |
| ) |
| { |
| if (module && name_cstr && name_cstr[0]) |
| { |
| SymbolContextList sc_list; |
| |
| SymbolVendor *symbol_vendor = module->GetSymbolVendor(); |
| if (symbol_vendor) |
| { |
| TypeList type_list; |
| uint32_t num_matches = 0; |
| SymbolContext sc; |
| // if (name_is_regex) |
| // { |
| // RegularExpression name_regex (name_cstr); |
| // num_matches = symbol_vendor->FindFunctions(sc, name_regex, true, UINT32_MAX, type_list); |
| // } |
| // else |
| // { |
| ConstString name(name_cstr); |
| num_matches = symbol_vendor->FindTypes(sc, name, true, UINT32_MAX, type_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"); |
| const uint32_t num_types = type_list.GetSize(); |
| for (uint32_t i=0; i<num_types; ++i) |
| { |
| TypeSP type_sp (type_list.GetTypeAtIndex(i)); |
| if (type_sp) |
| { |
| // Resolve the clang type so that any forward references |
| // to types that haven't yet been parsed will get parsed. |
| type_sp->GetOpaqueClangQualType (); |
| type_sp->GetDescription (&strm, eDescriptionLevelFull, true); |
| } |
| strm.EOL(); |
| } |
| } |
| return num_matches; |
| } |
| } |
| return 0; |
| } |
| |
| static uint32_t |
| LookupFileAndLineInModule (CommandInterpreter &interpreter, 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 (interpreter, 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 (CommandInterpreter &interpreter, |
| Args &input, |
| int &cursor_index, |
| int &cursor_char_position, |
| OptionElementVector &opt_element_vector, |
| int match_start_point, |
| int max_return_elements, |
| bool &word_complete, |
| StringList &matches) |
| { |
| // Arguments are the standard module completer. |
| std::string completion_str (input.GetArgumentAtIndex(cursor_index)); |
| completion_str.erase (cursor_char_position); |
| |
| CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, |
| CommandCompletions::eModuleCompletion, |
| completion_str.c_str(), |
| match_start_point, |
| max_return_elements, |
| NULL, |
| word_complete, |
| 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 (CommandInterpreter &interpreter, |
| Args &input, |
| int &cursor_index, |
| int &cursor_char_position, |
| OptionElementVector &opt_element_vector, |
| int match_start_point, |
| int max_return_elements, |
| bool &word_complete, |
| 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 (interpreter, |
| CommandCompletions::eSourceFileCompletion, |
| completion_str.c_str(), |
| match_start_point, |
| max_return_elements, |
| NULL, |
| word_complete, |
| 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| 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 (interpreter, 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; |
| size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); |
| |
| // Not found in our module list for our target, check the main |
| // shared module list in case it is a extra file used somewhere |
| // else |
| if (num_matching_modules == 0) |
| num_matching_modules = ModuleList::FindSharedModules (image_file, |
| target->GetArchitecture(), |
| 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 (interpreter, 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| 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 (interpreter, 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; |
| size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); |
| |
| // Not found in our module list for our target, check the main |
| // shared module list in case it is a extra file used somewhere |
| // else |
| if (num_matching_modules == 0) |
| num_matching_modules = ModuleList::FindSharedModules (image_file, |
| target->GetArchitecture(), |
| 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 (interpreter, 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| 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; |
| size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); |
| |
| // Not found in our module list for our target, check the main |
| // shared module list in case it is a extra file used somewhere |
| // else |
| if (num_matching_modules == 0) |
| num_matching_modules = ModuleList::FindSharedModules (image_file, |
| target->GetArchitecture(), |
| 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| if (target == NULL) |
| { |
| result.AppendError ("invalid target, set executable file using 'file' command"); |
| result.SetStatus (eReturnStatusFailed); |
| return false; |
| } |
| else |
| { |
| ExecutionContext exe_ctx(interpreter.GetDebugger().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 (interpreter, |
| 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 (interpreter, "symtab", CommandObjectSP (new CommandObjectImageDumpSymtab ())); |
| LoadSubCommand (interpreter, "sections", CommandObjectSP (new CommandObjectImageDumpSections ())); |
| LoadSubCommand (interpreter, "symfile", CommandObjectSP (new CommandObjectImageDumpSymfile ())); |
| LoadSubCommand (interpreter, "line-table", CommandObjectSP (new CommandObjectImageDumpLineTable ())); |
| } |
| |
| 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| 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[] = |
| { |
| { LLDB_OPT_SET_1, false, "arch", 'a', optional_argument, NULL, 0, "<width>", "Display the architecture when listing images."}, |
| { LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, NULL, "Display the UUID when listing images."}, |
| { LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image object file."}, |
| { LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, "<width>", "Display the directory with optional width for the image object file."}, |
| { LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, "<width>", "Display the basename with optional width for the image object file."}, |
| { LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image symbol file with optional width."}, |
| { LLDB_OPT_SET_1, 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, |
| eLookupTypeType, |
| 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 't': |
| m_str = option_arg; |
| m_type = eLookupTypeType; |
| break; |
| |
| case 'v': |
| m_verbose = 1; |
| 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; |
| m_verbose = false; |
| } |
| |
| 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. |
| bool m_verbose; // Enable verbose lookup info |
| |
| }; |
| |
| 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 (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error) |
| { |
| switch (m_options.m_type) |
| { |
| case eLookupTypeAddress: |
| if (m_options.m_addr != LLDB_INVALID_ADDRESS) |
| { |
| if (LookupAddressInModule (interpreter, |
| result.GetOutputStream(), |
| module, |
| eSymbolContextEverything, |
| m_options.m_addr, |
| m_options.m_offset, |
| m_options.m_verbose)) |
| { |
| result.SetStatus(eReturnStatusSuccessFinishResult); |
| return true; |
| } |
| } |
| break; |
| |
| case eLookupTypeSymbol: |
| if (!m_options.m_str.empty()) |
| { |
| if (LookupSymbolInModule (interpreter, 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 (interpreter, |
| 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 (interpreter, |
| result.GetOutputStream(), |
| module, |
| m_options.m_str.c_str(), |
| m_options.m_use_regex)) |
| { |
| result.SetStatus(eReturnStatusSuccessFinishResult); |
| return true; |
| } |
| } |
| break; |
| |
| case eLookupTypeType: |
| if (!m_options.m_str.empty()) |
| { |
| if (LookupTypeInModule (interpreter, |
| 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 (CommandInterpreter &interpreter, |
| Args& command, |
| CommandReturnObject &result) |
| { |
| Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); |
| 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 (interpreter, 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; |
| size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); |
| |
| // Not found in our module list for our target, check the main |
| // shared module list in case it is a extra file used somewhere |
| // else |
| if (num_matching_modules == 0) |
| num_matching_modules = ModuleList::FindSharedModules (image_file, |
| target->GetArchitecture(), |
| NULL, |
| NULL, |
| matching_modules); |
| |
| if (num_matching_modules > 0) |
| { |
| for (size_t j=0; j<num_matching_modules; ++j) |
| { |
| Module * image_module = matching_modules.GetModulePointerAtIndex(j); |
| if (image_module) |
| { |
| if (LookupInModule (interpreter, 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[] = |
| { |
| { LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, "<addr>", "Lookup an address in one or more executable images."}, |
| { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, "<offset>", "When looking up an address subtract <offset> from any addresses before doing the lookup."}, |
| { LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, "<name>", "Lookup a symbol by name in the symbol tables in one or more executable images."}, |
| { LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."}, |
| { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, "<file>", "Lookup a file by fullpath or basename in one or more executable images."}, |
| { LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, "<line>", "Lookup a line number in a file (must be used in conjunction with --file)."}, |
| { LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument, NULL, 0, NULL, "Check inline line entries (must be used in conjunction with --file)."}, |
| { LLDB_OPT_SET_4, true, "function", 'n', required_argument, NULL, 0, "<name>", "Lookup a function by name in the debug symbols in one or more executable images."}, |
| { LLDB_OPT_SET_5, true, "type", 't', required_argument, NULL, 0, "<name>", "Lookup a type by name in the debug symbols in one or more executable images."}, |
| { LLDB_OPT_SET_ALL, false, "verbose", 'v', no_argument, NULL, 0, NULL, "Enable verbose lookup information."}, |
| { 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 (interpreter, "dump", CommandObjectSP (new CommandObjectImageDump (interpreter))); |
| LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectImageList ())); |
| LoadSubCommand (interpreter, "lookup", CommandObjectSP (new CommandObjectImageLookup ())); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Destructor |
| //---------------------------------------------------------------------- |
| CommandObjectImage::~CommandObjectImage() |
| { |
| } |
| |