diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:06:29 +0000 |
| commit | 94994d372d014ce4c8758b9605d63fae651bd8aa (patch) | |
| tree | 51c0b708bd59f205d6b35cb2a8c24d62f0c33d77 /tools/lldb-test | |
| parent | 39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff) | |
Notes
Diffstat (limited to 'tools/lldb-test')
| -rw-r--r-- | tools/lldb-test/FormatUtil.cpp | 47 | ||||
| -rw-r--r-- | tools/lldb-test/FormatUtil.h | 27 | ||||
| -rw-r--r-- | tools/lldb-test/SystemInitializerTest.cpp | 40 | ||||
| -rw-r--r-- | tools/lldb-test/SystemInitializerTest.h | 2 | ||||
| -rw-r--r-- | tools/lldb-test/lldb-test.cpp | 290 |
5 files changed, 261 insertions, 145 deletions
diff --git a/tools/lldb-test/FormatUtil.cpp b/tools/lldb-test/FormatUtil.cpp index 381cbd6e25b8..970f25a6b42f 100644 --- a/tools/lldb-test/FormatUtil.cpp +++ b/tools/lldb-test/FormatUtil.cpp @@ -14,6 +14,11 @@ using namespace lldb_private; using namespace llvm; +LinePrinter::Line::~Line() { + if (P) + P->NewLine(); +} + LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream) : OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {} @@ -31,39 +36,31 @@ void LinePrinter::Unindent(uint32_t Amount) { void LinePrinter::NewLine() { OS << "\n"; - OS.indent(CurrentIndent); -} - -void LinePrinter::print(const Twine &T) { OS << T; } - -void LinePrinter::printLine(const Twine &T) { - NewLine(); - OS << T; } void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint32_t StartOffset) { - NewLine(); - OS << Label << " ("; - if (!Data.empty()) { - OS << "\n"; - OS << format_bytes_with_ascii(Data, StartOffset, 32, 4, - CurrentIndent + IndentSpaces, true); - NewLine(); + if (Data.empty()) { + line() << Label << " ()"; + return; } - OS << ")"; + line() << Label << " ("; + OS << format_bytes_with_ascii(Data, StartOffset, 32, 4, + CurrentIndent + IndentSpaces, true); + NewLine(); + line() << ")"; } void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, uint64_t Base, uint32_t StartOffset) { - NewLine(); - OS << Label << " ("; - if (!Data.empty()) { - OS << "\n"; - Base += StartOffset; - OS << format_bytes_with_ascii(Data, Base, 32, 4, - CurrentIndent + IndentSpaces, true); - NewLine(); + if (Data.empty()) { + line() << Label << " ()"; + return; } - OS << ")"; + line() << Label << " ("; + Base += StartOffset; + OS << format_bytes_with_ascii(Data, Base, 32, 4, CurrentIndent + IndentSpaces, + true); + NewLine(); + line() << ")"; } diff --git a/tools/lldb-test/FormatUtil.h b/tools/lldb-test/FormatUtil.h index f22ee41662ee..598d4c5440f5 100644 --- a/tools/lldb-test/FormatUtil.h +++ b/tools/lldb-test/FormatUtil.h @@ -26,27 +26,36 @@ class LinePrinter { int CurrentIndent; public: + class Line { + LinePrinter *P; + + public: + Line(LinePrinter &P) : P(&P) { P.OS.indent(P.CurrentIndent); } + ~Line(); + + Line(Line &&RHS) : P(RHS.P) { RHS.P = nullptr; } + void operator=(Line &&) = delete; + + operator llvm::raw_ostream &() { return P->OS; } + }; + LinePrinter(int Indent, llvm::raw_ostream &Stream); void Indent(uint32_t Amount = 0); void Unindent(uint32_t Amount = 0); void NewLine(); - void printLine(const llvm::Twine &T); - void print(const llvm::Twine &T); + void printLine(const llvm::Twine &T) { line() << T; } template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) { printLine(llvm::formatv(Fmt, std::forward<Ts>(Items)...)); } - template <typename... Ts> void format(const char *Fmt, Ts &&... Items) { - print(llvm::formatv(Fmt, std::forward<Ts>(Items)...)); - } void formatBinary(llvm::StringRef Label, llvm::ArrayRef<uint8_t> Data, uint32_t StartOffset); void formatBinary(llvm::StringRef Label, llvm::ArrayRef<uint8_t> Data, uint64_t BaseAddr, uint32_t StartOffset); - llvm::raw_ostream &getStream() { return OS; } + Line line() { return Line(*this); } int getIndentLevel() const { return CurrentIndent; } }; @@ -64,12 +73,6 @@ struct AutoIndent { uint32_t Amount = 0; }; -template <class T> -inline llvm::raw_ostream &operator<<(LinePrinter &Printer, const T &Item) { - Printer.getStream() << Item; - return Printer.getStream(); -} - } // namespace lldb_private #endif diff --git a/tools/lldb-test/SystemInitializerTest.cpp b/tools/lldb-test/SystemInitializerTest.cpp index 2c190ecfc745..1220312def84 100644 --- a/tools/lldb-test/SystemInitializerTest.cpp +++ b/tools/lldb-test/SystemInitializerTest.cpp @@ -14,9 +14,6 @@ #include "lldb/Initialization/SystemInitializerCommon.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/GoASTContext.h" -#include "lldb/Symbol/JavaASTContext.h" -#include "lldb/Symbol/OCamlASTContext.h" #include "lldb/Utility/Timer.h" #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" @@ -48,22 +45,17 @@ #include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h" #include "Plugins/JITLoader/GDB/JITLoaderGDB.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" -#include "Plugins/Language/Go/GoLanguage.h" -#include "Plugins/Language/Java/JavaLanguage.h" -#include "Plugins/Language/OCaml/OCamlLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h" #include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h" -#include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h" -#include "Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h" #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h" +#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" -#include "Plugins/OperatingSystem/Go/OperatingSystemGo.h" #include "Plugins/Platform/Android/PlatformAndroid.h" #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" #include "Plugins/Platform/Kalimba/PlatformKalimba.h" @@ -78,6 +70,7 @@ #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" #include "Plugins/Process/minidump/ProcessMinidump.h" #include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h" +#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h" #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" @@ -120,16 +113,18 @@ SystemInitializerTest::SystemInitializerTest() {} SystemInitializerTest::~SystemInitializerTest() {} -void SystemInitializerTest::Initialize() { - SystemInitializerCommon::Initialize(); +llvm::Error +SystemInitializerTest::Initialize(const InitializerOptions &options) { + if (auto e = SystemInitializerCommon::Initialize(options)) + return e; + breakpad::ObjectFileBreakpad::Initialize(); ObjectFileELF::Initialize(); ObjectFileMachO::Initialize(); ObjectFilePECOFF::Initialize(); ScriptInterpreterNone::Initialize(); - OperatingSystemGo::Initialize(); platform_freebsd::PlatformFreeBSD::Initialize(); platform_linux::PlatformLinux::Initialize(); @@ -152,9 +147,6 @@ void SystemInitializerTest::Initialize() { llvm::InitializeAllDisassemblers(); ClangASTContext::Initialize(); - GoASTContext::Initialize(); - JavaASTContext::Initialize(); - OCamlASTContext::Initialize(); ABIMacOSX_i386::Initialize(); ABIMacOSX_arm::Initialize(); @@ -185,6 +177,7 @@ void SystemInitializerTest::Initialize() { MainThreadCheckerRuntime::Initialize(); SymbolVendorELF::Initialize(); + breakpad::SymbolFileBreakpad::Initialize(); SymbolFileDWARF::Initialize(); SymbolFilePDB::Initialize(); SymbolFileSymtab::Initialize(); @@ -198,15 +191,10 @@ void SystemInitializerTest::Initialize() { AppleObjCRuntimeV1::Initialize(); SystemRuntimeMacOSX::Initialize(); RenderScriptRuntime::Initialize(); - GoLanguageRuntime::Initialize(); - JavaLanguageRuntime::Initialize(); CPlusPlusLanguage::Initialize(); - GoLanguage::Initialize(); - JavaLanguage::Initialize(); ObjCLanguage::Initialize(); ObjCPlusPlusLanguage::Initialize(); - OCamlLanguage::Initialize(); #if defined(_WIN32) ProcessWindows::Initialize(); @@ -249,6 +237,8 @@ void SystemInitializerTest::Initialize() { // AFTER PluginManager::Initialize is called. Debugger::SettingsInitialize(); + + return llvm::Error::success(); } void SystemInitializerTest::Terminate() { @@ -261,9 +251,6 @@ void SystemInitializerTest::Terminate() { PluginManager::Terminate(); ClangASTContext::Terminate(); - GoASTContext::Terminate(); - JavaASTContext::Terminate(); - OCamlASTContext::Terminate(); ABIMacOSX_i386::Terminate(); ABIMacOSX_arm::Terminate(); @@ -289,6 +276,7 @@ void SystemInitializerTest::Terminate() { UndefinedBehaviorSanitizerRuntime::Terminate(); MainThreadCheckerRuntime::Terminate(); SymbolVendorELF::Terminate(); + breakpad::SymbolFileBreakpad::Terminate(); SymbolFileDWARF::Terminate(); SymbolFilePDB::Terminate(); SymbolFileSymtab::Terminate(); @@ -302,14 +290,10 @@ void SystemInitializerTest::Terminate() { AppleObjCRuntimeV1::Terminate(); SystemRuntimeMacOSX::Terminate(); RenderScriptRuntime::Terminate(); - JavaLanguageRuntime::Terminate(); CPlusPlusLanguage::Terminate(); - GoLanguage::Terminate(); - JavaLanguage::Terminate(); ObjCLanguage::Terminate(); ObjCPlusPlusLanguage::Terminate(); - OCamlLanguage::Terminate(); #if defined(__APPLE__) DynamicLoaderDarwinKernel::Terminate(); @@ -337,7 +321,6 @@ void SystemInitializerTest::Terminate() { DynamicLoaderStatic::Terminate(); DynamicLoaderWindowsDYLD::Terminate(); - OperatingSystemGo::Terminate(); platform_freebsd::PlatformFreeBSD::Terminate(); platform_linux::PlatformLinux::Terminate(); @@ -353,6 +336,7 @@ void SystemInitializerTest::Terminate() { PlatformDarwinKernel::Terminate(); #endif + breakpad::ObjectFileBreakpad::Terminate(); ObjectFileELF::Terminate(); ObjectFileMachO::Terminate(); ObjectFilePECOFF::Terminate(); diff --git a/tools/lldb-test/SystemInitializerTest.h b/tools/lldb-test/SystemInitializerTest.h index 887d6243765d..5950ff725ff0 100644 --- a/tools/lldb-test/SystemInitializerTest.h +++ b/tools/lldb-test/SystemInitializerTest.h @@ -26,7 +26,7 @@ public: SystemInitializerTest(); ~SystemInitializerTest() override; - void Initialize() override; + llvm::Error Initialize(const InitializerOptions &options) override; void Terminate() override; }; diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp index c9225f63d303..f7bfc487c0ce 100644 --- a/tools/lldb-test/lldb-test.cpp +++ b/tools/lldb-test/lldb-test.cpp @@ -30,6 +30,7 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/IntervalMap.h" @@ -90,19 +91,27 @@ namespace object { cl::opt<bool> SectionContents("contents", cl::desc("Dump each section's contents"), cl::sub(ObjectFileSubcommand)); +cl::opt<bool> SectionDependentModules("dep-modules", + cl::desc("Dump each dependent module"), + cl::sub(ObjectFileSubcommand)); cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"), cl::OneOrMore, cl::sub(ObjectFileSubcommand)); } // namespace object namespace symbols { -static cl::list<std::string> InputFilenames(cl::Positional, - cl::desc("<input files>"), - cl::OneOrMore, - cl::sub(SymbolsSubcommand)); +static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"), + cl::Required, cl::sub(SymbolsSubcommand)); + +static cl::opt<std::string> + SymbolPath("symbol-file", + cl::desc("The file from which to fetch symbol information."), + cl::value_desc("file"), cl::sub(SymbolsSubcommand)); + enum class FindType { None, Function, + Block, Namespace, Type, Variable, @@ -112,6 +121,7 @@ static cl::opt<FindType> Find( cl::values( clEnumValN(FindType::None, "none", "No search, just dump the module."), clEnumValN(FindType::Function, "function", "Find functions."), + clEnumValN(FindType::Block, "block", "Find blocks."), clEnumValN(FindType::Namespace, "namespace", "Find namespaces."), clEnumValN(FindType::Type, "type", "Find types."), clEnumValN(FindType::Variable, "variable", "Find global variables.")), @@ -146,6 +156,10 @@ static FunctionNameType getFunctionNameFlags() { return Result; } +static cl::opt<bool> DumpAST("dump-ast", + cl::desc("Dump AST restored from symbols."), + cl::sub(SymbolsSubcommand)); + static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."), cl::sub(SymbolsSubcommand)); @@ -158,10 +172,12 @@ static cl::opt<int> Line("line", cl::desc("Line to search."), static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor); static Error findFunctions(lldb_private::Module &Module); +static Error findBlocks(lldb_private::Module &Module); static Error findNamespaces(lldb_private::Module &Module); static Error findTypes(lldb_private::Module &Module); static Error findVariables(lldb_private::Module &Module); static Error dumpModule(lldb_private::Module &Module); +static Error dumpAST(lldb_private::Module &Module); static Error verify(lldb_private::Module &Module); static Expected<Error (*)(lldb_private::Module &)> getAction(); @@ -197,7 +213,6 @@ struct IRMemoryMapTestState { : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {} }; -bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R); bool evalMalloc(StringRef Line, IRMemoryMapTestState &State); bool evalFree(StringRef Line, IRMemoryMapTestState &State); int evaluateMemoryMapCommands(Debugger &Dbg); @@ -214,10 +229,9 @@ static Error make_string_error(const char *Format, Args &&... args) { TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) { TargetSP Target; - Status ST = - Dbg.GetTargetList().CreateTarget(Dbg, Filename, /*triple*/ "", - /*get_dependent_modules*/ false, - /*platform_options*/ nullptr, Target); + Status ST = Dbg.GetTargetList().CreateTarget( + Dbg, Filename, /*triple*/ "", eLoadDependentsNo, + /*platform_options*/ nullptr, Target); if (ST.Fail()) { errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST); exit(1); @@ -278,7 +292,7 @@ std::string opts::breakpoint::substitute(StringRef Cmd) { OS << sys::path::parent_path(breakpoint::CommandFile); break; } - // fall through + LLVM_FALLTHROUGH; default: size_t pos = Cmd.find('%'); OS << Cmd.substr(0, pos); @@ -340,7 +354,7 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) { if (!File.empty()) { assert(Line != 0); - FileSpec src_file(File, false); + FileSpec src_file(File); size_t cu_count = Module.GetNumCompileUnits(); for (size_t i = 0; i < cu_count; i++) { lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); @@ -383,6 +397,42 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) { return Error::success(); } +Error opts::symbols::findBlocks(lldb_private::Module &Module) { + assert(!Regex); + assert(!File.empty()); + assert(Line != 0); + + SymbolContextList List; + + FileSpec src_file(File); + size_t cu_count = Module.GetNumCompileUnits(); + for (size_t i = 0; i < cu_count; i++) { + lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i); + if (!cu_sp) + continue; + + LineEntry le; + cu_sp->FindLineEntry(0, Line, &src_file, false, &le); + if (!le.IsValid()) + continue; + + auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress(); + if (!addr.IsValid()) + continue; + + SymbolContext sc; + uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock); + if (resolved & eSymbolContextBlock) + List.Append(sc); + } + + outs() << formatv("Found {0} blocks:\n", List.GetSize()); + StreamString Stream; + List.Dump(&Stream, nullptr); + outs() << Stream.GetData() << "\n"; + return Error::success(); +} + Error opts::symbols::findNamespaces(lldb_private::Module &Module) { SymbolVendor &Vendor = *Module.GetSymbolVendor(); Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor); @@ -391,9 +441,8 @@ Error opts::symbols::findNamespaces(lldb_private::Module &Module) { CompilerDeclContext *ContextPtr = ContextOr->IsValid() ? &*ContextOr : nullptr; - SymbolContext SC; CompilerDeclContext Result = - Vendor.FindNamespace(SC, ConstString(Name), ContextPtr); + Vendor.FindNamespace(ConstString(Name), ContextPtr); if (Result) outs() << "Found namespace: " << Result.GetScopeQualifiedName().GetStringRef() << "\n"; @@ -410,10 +459,9 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { CompilerDeclContext *ContextPtr = ContextOr->IsValid() ? &*ContextOr : nullptr; - SymbolContext SC; DenseSet<SymbolFile *> SearchedFiles; TypeMap Map; - Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX, + Vendor.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX, SearchedFiles, Map); outs() << formatv("Found {0} types:\n", Map.GetSize()); @@ -470,6 +518,32 @@ Error opts::symbols::dumpModule(lldb_private::Module &Module) { return Error::success(); } +Error opts::symbols::dumpAST(lldb_private::Module &Module) { + SymbolVendor &plugin = *Module.GetSymbolVendor(); + Module.ParseAllDebugSymbols(); + + auto symfile = plugin.GetSymbolFile(); + if (!symfile) + return make_string_error("Module has no symbol file."); + + auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>( + symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus)); + if (!clang_ast_ctx) + return make_string_error("Can't retrieve Clang AST context."); + + auto ast_ctx = clang_ast_ctx->getASTContext(); + if (!ast_ctx) + return make_string_error("Can't retrieve AST context."); + + auto tu = ast_ctx->getTranslationUnitDecl(); + if (!tu) + return make_string_error("Can't retrieve translation unit declaration."); + + tu->print(outs()); + + return Error::success(); +} + Error opts::symbols::verify(lldb_private::Module &Module) { SymbolVendor &plugin = *Module.GetSymbolVendor(); @@ -523,6 +597,10 @@ Error opts::symbols::verify(lldb_private::Module &Module) { } Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { + if (Verify && DumpAST) + return make_string_error( + "Cannot both verify symbol information and dump AST."); + if (Verify) { if (Find != FindType::None) return make_string_error( @@ -535,6 +613,17 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { return verify; } + if (DumpAST) { + if (Find != FindType::None) + return make_string_error("Cannot both search and dump AST."); + if (Regex || !Context.empty() || !Name.empty() || !File.empty() || + Line != 0) + return make_string_error( + "-regex, -context, -name, -file and -line options are not " + "applicable for dumping AST."); + return dumpAST; + } + if (Regex && !Context.empty()) return make_string_error( "Cannot search using both regular expressions and context."); @@ -566,6 +655,15 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { "when searching a function."); return findFunctions; + case FindType::Block: + if (File.empty() || Line == 0) + return make_string_error("Both file name and line number must be " + "specified when searching a block."); + if (Regex || getFunctionNameFlags() != 0) + return make_string_error("Cannot use regular expression or " + "function-flags for searching a block."); + return findBlocks; + case FindType::Namespace: if (Regex || !File.empty() || Line != 0) return make_string_error("Cannot search for namespaces using regular " @@ -584,6 +682,8 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() { "using line numbers."); return findVariables; } + + llvm_unreachable("Unsupported symbol action."); } int opts::symbols::dumpSymbols(Debugger &Dbg) { @@ -594,28 +694,59 @@ int opts::symbols::dumpSymbols(Debugger &Dbg) { } auto Action = *ActionOr; - int HadErrors = 0; - for (const auto &File : InputFilenames) { - outs() << "Module: " << File << "\n"; - ModuleSpec Spec{FileSpec(File, false)}; - Spec.GetSymbolFileSpec().SetFile(File, false, FileSpec::Style::native); + outs() << "Module: " << InputFile << "\n"; + ModuleSpec Spec{FileSpec(InputFile)}; + StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath; + Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native); - auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); - SymbolVendor *Vendor = ModulePtr->GetSymbolVendor(); - if (!Vendor) { - WithColor::error() << "Module has no symbol vendor.\n"; - HadErrors = 1; - continue; - } + auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); + SymbolVendor *Vendor = ModulePtr->GetSymbolVendor(); + if (!Vendor) { + WithColor::error() << "Module has no symbol vendor.\n"; + return 1; + } - if (Error E = Action(*ModulePtr)) { - WithColor::error() << toString(std::move(E)) << "\n"; - HadErrors = 1; + if (Error E = Action(*ModulePtr)) { + WithColor::error() << toString(std::move(E)) << "\n"; + return 1; + } + + return 0; +} + +static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) { + size_t Count = List.GetNumSections(0); + if (Count == 0) { + Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : ""); + return; + } + Printer.formatLine("Showing {0} {1}sections", Count, + is_subsection ? "sub" : ""); + for (size_t I = 0; I < Count; ++I) { + auto S = List.GetSectionAtIndex(I); + assert(S); + AutoIndent Indent(Printer, 2); + Printer.formatLine("Index: {0}", I); + Printer.formatLine("ID: {0:x}", S->GetID()); + Printer.formatLine("Name: {0}", S->GetName().GetStringRef()); + Printer.formatLine("Type: {0}", S->GetTypeAsCString()); + Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions())); + Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific()); + Printer.formatLine("VM address: {0:x}", S->GetFileAddress()); + Printer.formatLine("VM size: {0}", S->GetByteSize()); + Printer.formatLine("File size: {0}", S->GetFileSize()); + + if (opts::object::SectionContents) { + DataExtractor Data; + S->GetSectionData(Data); + ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()}; + Printer.formatBinary("Data: ", Bytes, 0); } - outs().flush(); + if (S->GetType() == eSectionTypeContainer) + dumpSectionList(Printer, S->GetChildren(), true); + Printer.NewLine(); } - return HadErrors; } static int dumpObjectFiles(Debugger &Dbg) { @@ -623,9 +754,17 @@ static int dumpObjectFiles(Debugger &Dbg) { int HadErrors = 0; for (const auto &File : opts::object::InputFilenames) { - ModuleSpec Spec{FileSpec(File, false)}; + ModuleSpec Spec{FileSpec(File)}; auto ModulePtr = std::make_shared<lldb_private::Module>(Spec); + + ObjectFile *ObjectPtr = ModulePtr->GetObjectFile(); + if (!ObjectPtr) { + WithColor::error() << File << " not recognised as an object file\n"; + HadErrors = 1; + continue; + } + // Fetch symbol vendor before we get the section list to give the symbol // vendor a chance to populate it. ModulePtr->GetSymbolVendor(); @@ -636,27 +775,29 @@ static int dumpObjectFiles(Debugger &Dbg) { continue; } + Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName()); Printer.formatLine("Architecture: {0}", ModulePtr->GetArchitecture().GetTriple().getTriple()); Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); - - size_t Count = Sections->GetNumSections(0); - Printer.formatLine("Showing {0} sections", Count); - for (size_t I = 0; I < Count; ++I) { - AutoIndent Indent(Printer, 2); - auto S = Sections->GetSectionAtIndex(I); - assert(S); - Printer.formatLine("Index: {0}", I); - Printer.formatLine("Name: {0}", S->GetName().GetStringRef()); - Printer.formatLine("Type: {0}", S->GetTypeAsCString()); - Printer.formatLine("VM size: {0}", S->GetByteSize()); - Printer.formatLine("File size: {0}", S->GetFileSize()); - - if (opts::object::SectionContents) { - DataExtractor Data; - S->GetSectionData(Data); - ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()}; - Printer.formatBinary("Data: ", Bytes, 0); + Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable()); + Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped()); + Printer.formatLine("Type: {0}", ObjectPtr->GetType()); + Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata()); + Printer.formatLine("Base VM address: {0:x}", + ObjectPtr->GetBaseAddress().GetFileAddress()); + + dumpSectionList(Printer, *Sections, /*is_subsection*/ false); + + if (opts::object::SectionDependentModules) { + // A non-empty section list ensures a valid object file. + auto Obj = ModulePtr->GetObjectFile(); + FileSpecList Files; + auto Count = Obj->GetDependentModules(Files); + Printer.formatLine("Showing {0} dependent module(s)", Count); + for (size_t I = 0; I < Files.GetSize(); ++I) { + AutoIndent Indent(Printer, 2); + Printer.formatLine("Name: {0}", + Files.GetFileSpecAtIndex(I).GetCString()); } Printer.NewLine(); } @@ -664,13 +805,6 @@ static int dumpObjectFiles(Debugger &Dbg) { return HadErrors; } -/// Check if two half-open intervals intersect: -/// http://world.std.com/~swmcd/steven/tech/interval.html -bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L, - const AllocationT &R) { - return R.first < L.second && L.first < R.second; -} - bool opts::irmemorymap::evalMalloc(StringRef Line, IRMemoryMapTestState &State) { // ::= <label> = malloc <size> <alignment> @@ -717,28 +851,21 @@ bool opts::irmemorymap::evalMalloc(StringRef Line, exit(1); } - // Check that the allocation does not overlap another allocation. Do so by - // testing each allocation which may cover the interval [Addr, EndOfRegion). - addr_t EndOfRegion = Addr + Size; - auto Probe = State.Allocations.begin(); - Probe.advanceTo(Addr); //< First interval s.t stop >= Addr. - AllocationT NewAllocation = {Addr, EndOfRegion}; - while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) { - AllocationT ProbeAllocation = {Probe.start(), Probe.stop()}; - if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) { - outs() << "Malloc error: overlapping allocation detected" - << formatv(", previous allocation at [{0:x}, {1:x})\n", - Probe.start(), Probe.stop()); - exit(1); - } - ++Probe; + // In case of Size == 0, we still expect the returned address to be unique and + // non-overlapping. + addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1); + if (State.Allocations.overlaps(Addr, EndOfRegion)) { + auto I = State.Allocations.find(Addr); + outs() << "Malloc error: overlapping allocation detected" + << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(), + I.stop()); + exit(1); } - // Insert the new allocation into the interval map. Use unique allocation IDs - // to inhibit interval coalescing. + // Insert the new allocation into the interval map. Use unique allocation + // IDs to inhibit interval coalescing. static unsigned AllocationID = 0; - if (Size) - State.Allocations.insert(Addr, EndOfRegion, AllocationID++); + State.Allocations.insert(Addr, EndOfRegion, AllocationID++); // Store the label -> address mapping. State.Label2AddrMap[Label] = Addr; @@ -836,8 +963,13 @@ int main(int argc, const char *argv[]) { cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n"); SystemLifetimeManager DebuggerLifetime; - DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(), - nullptr); + if (auto e = DebuggerLifetime.Initialize( + llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) { + WithColor::error() << "initialization failed: " << toString(std::move(e)) + << '\n'; + return 1; + } + CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); }); auto Dbg = lldb_private::Debugger::CreateInstance(); |
