diff options
author | 2020-08-03 14:33:06 +0000 | |
---|---|---|
committer | 2020-08-03 14:33:06 +0000 | |
commit | 061da546b983eb767bad15e67af1174fb0bcf31c (patch) | |
tree | 83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/tools/lldb-test | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/tools/lldb-test')
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/CMakeLists.txt | 27 | ||||
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/FormatUtil.cpp | 65 | ||||
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/FormatUtil.h | 77 | ||||
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.cpp | 351 | ||||
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.h | 32 | ||||
-rw-r--r-- | gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp | 1103 |
6 files changed, 1655 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/tools/lldb-test/CMakeLists.txt b/gnu/llvm/lldb/tools/lldb-test/CMakeLists.txt new file mode 100644 index 00000000000..2ab1ceacdcd --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/CMakeLists.txt @@ -0,0 +1,27 @@ +get_property(LLDB_ALL_PLUGINS GLOBAL PROPERTY LLDB_PLUGINS) + +add_lldb_tool(lldb-test + FormatUtil.cpp + lldb-test.cpp + SystemInitializerTest.cpp + + LINK_LIBS + lldbBase + lldbBreakpoint + lldbCore + lldbDataFormatters + lldbExpression + lldbHost + lldbInitialization + lldbInterpreter + lldbSymbol + lldbTarget + lldbUtility + ${LLDB_ALL_PLUGINS} + ${host_lib} + + LINK_COMPONENTS + Support + ) + +include_directories(${LLDB_SOURCE_DIR}/source) diff --git a/gnu/llvm/lldb/tools/lldb-test/FormatUtil.cpp b/gnu/llvm/lldb/tools/lldb-test/FormatUtil.cpp new file mode 100644 index 00000000000..1e5e1ee0874 --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/FormatUtil.cpp @@ -0,0 +1,65 @@ +//===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FormatUtil.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" + +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) {} + +void LinePrinter::Indent(uint32_t Amount) { + if (Amount == 0) + Amount = IndentSpaces; + CurrentIndent += Amount; +} + +void LinePrinter::Unindent(uint32_t Amount) { + if (Amount == 0) + Amount = IndentSpaces; + CurrentIndent = std::max<int>(0, CurrentIndent - Amount); +} + +void LinePrinter::NewLine() { + OS << "\n"; +} + +void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, + uint32_t StartOffset) { + if (Data.empty()) { + line() << Label << " ()"; + return; + } + 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) { + if (Data.empty()) { + line() << Label << " ()"; + return; + } + line() << Label << " ("; + Base += StartOffset; + OS << format_bytes_with_ascii(Data, Base, 32, 4, CurrentIndent + IndentSpaces, + true); + NewLine(); + line() << ")"; +} diff --git a/gnu/llvm/lldb/tools/lldb-test/FormatUtil.h b/gnu/llvm/lldb/tools/lldb-test/FormatUtil.h new file mode 100644 index 00000000000..91b3c085b60 --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/FormatUtil.h @@ -0,0 +1,77 @@ +//===- FormatUtil.h ------------------------------------------- *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLDBTEST_FORMATUTIL_H +#define LLVM_TOOLS_LLDBTEST_FORMATUTIL_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" + +#include <list> + +namespace lldb_private { + +class LinePrinter { + llvm::raw_ostream &OS; + int IndentSpaces; + 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) { line() << T; } + template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) { + printLine(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); + + Line line() { return Line(*this); } + int getIndentLevel() const { return CurrentIndent; } +}; + +struct AutoIndent { + explicit AutoIndent(LinePrinter &L, uint32_t Amount = 0) + : L(&L), Amount(Amount) { + L.Indent(Amount); + } + ~AutoIndent() { + if (L) + L->Unindent(Amount); + } + + LinePrinter *L = nullptr; + uint32_t Amount = 0; +}; + +} // namespace lldb_private + +#endif diff --git a/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.cpp b/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.cpp new file mode 100644 index 00000000000..8841e4d6583 --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.cpp @@ -0,0 +1,351 @@ +//===-- SystemInitializerTest.cpp -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SystemInitializerTest.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Host/Host.h" +#include "lldb/Initialization/SystemInitializerCommon.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Utility/Timer.h" + +#include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" +#include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h" +#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h" +#include "Plugins/ABI/SysV-arm/ABISysV_arm.h" +#include "Plugins/ABI/SysV-arm64/ABISysV_arm64.h" +#include "Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h" +#include "Plugins/ABI/SysV-i386/ABISysV_i386.h" +#include "Plugins/ABI/SysV-mips/ABISysV_mips.h" +#include "Plugins/ABI/SysV-mips64/ABISysV_mips64.h" +#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h" +#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" +#include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h" +#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" +#include "Plugins/ABI/Windows-x86_64/ABIWindows_x86_64.h" +#include "Plugins/Architecture/Arm/ArchitectureArm.h" +#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h" +#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h" +#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h" +#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" +#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" +#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h" +#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h" +#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h" +#include "Plugins/InstrumentationRuntime/ASan/ASanRuntime.h" +#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h" +#include "Plugins/InstrumentationRuntime/TSan/TSanRuntime.h" +#include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h" +#include "Plugins/JITLoader/GDB/JITLoaderGDB.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h" +#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.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/Platform/Android/PlatformAndroid.h" +#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" +#include "Plugins/Platform/Linux/PlatformLinux.h" +#include "Plugins/Platform/MacOSX/PlatformMacOSX.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" +#include "Plugins/Platform/NetBSD/PlatformNetBSD.h" +#include "Plugins/Platform/OpenBSD/PlatformOpenBSD.h" +#include "Plugins/Platform/Windows/PlatformWindows.h" +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" +#include "Plugins/Process/elf-core/ProcessElfCore.h" +#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" +#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" +#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h" +#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h" +#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h" +#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h" + +#if defined(__APPLE__) +#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" +#include "Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h" +#include "Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h" +#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h" +#include "Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h" +#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" +#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h" +#include "Plugins/Process/mach-core/ProcessMachCore.h" +#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h" +#endif +#include "Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.h" + +#if defined(__FreeBSD__) +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" +#endif + +#if defined(_WIN32) +#include "Plugins/Process/Windows/Common/ProcessWindows.h" +#include "lldb/Host/windows/windows.h" +#endif + +#include "llvm/Support/TargetSelect.h" + +#include <string> + +using namespace lldb_private; + +SystemInitializerTest::SystemInitializerTest() {} + +SystemInitializerTest::~SystemInitializerTest() {} + +#define LLDB_PROCESS_AArch64(op) \ + ABIMacOSX_arm64::op(); \ + ABISysV_arm64::op(); +#define LLDB_PROCESS_ARM(op) \ + ABIMacOSX_arm::op(); \ + ABISysV_arm::op(); +#define LLDB_PROCESS_Hexagon(op) ABISysV_hexagon::op(); +#define LLDB_PROCESS_Mips(op) \ + ABISysV_mips::op(); \ + ABISysV_mips64::op(); +#define LLDB_PROCESS_PowerPC(op) \ + ABISysV_ppc::op(); \ + ABISysV_ppc64::op(); +#define LLDB_PROCESS_SystemZ(op) ABISysV_s390x::op(); +#define LLDB_PROCESS_X86(op) \ + ABIMacOSX_i386::op(); \ + ABISysV_i386::op(); \ + ABISysV_x86_64::op(); \ + ABIWindows_x86_64::op(); + +#define LLDB_PROCESS_AMDGPU(op) +#define LLDB_PROCESS_ARC(op) +#define LLDB_PROCESS_AVR(op) +#define LLDB_PROCESS_BPF(op) +#define LLDB_PROCESS_Lanai(op) +#define LLDB_PROCESS_MSP430(op) +#define LLDB_PROCESS_NVPTX(op) +#define LLDB_PROCESS_RISCV(op) +#define LLDB_PROCESS_Sparc(op) +#define LLDB_PROCESS_WebAssembly(op) +#define LLDB_PROCESS_XCore(op) + +llvm::Error SystemInitializerTest::Initialize() { + if (auto e = SystemInitializerCommon::Initialize()) + return e; + + breakpad::ObjectFileBreakpad::Initialize(); + ObjectFileELF::Initialize(); + ObjectFileMachO::Initialize(); + ObjectFilePECOFF::Initialize(); + + ScriptInterpreterNone::Initialize(); + + + platform_freebsd::PlatformFreeBSD::Initialize(); + platform_linux::PlatformLinux::Initialize(); + platform_netbsd::PlatformNetBSD::Initialize(); + platform_openbsd::PlatformOpenBSD::Initialize(); + PlatformWindows::Initialize(); + platform_android::PlatformAndroid::Initialize(); + PlatformRemoteiOS::Initialize(); + PlatformMacOSX::Initialize(); +#if defined(__APPLE__) + PlatformiOSSimulator::Initialize(); + PlatformDarwinKernel::Initialize(); +#endif + + // Initialize LLVM and Clang + llvm::InitializeAllTargets(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + + ClangASTContext::Initialize(); + +#define LLVM_TARGET(t) LLDB_PROCESS_ ## t(Initialize) +#include "llvm/Config/Targets.def" + + ArchitectureArm::Initialize(); + ArchitecturePPC64::Initialize(); + + DisassemblerLLVMC::Initialize(); + + JITLoaderGDB::Initialize(); + ProcessElfCore::Initialize(); + minidump::ProcessMinidump::Initialize(); + MemoryHistoryASan::Initialize(); + AddressSanitizerRuntime::Initialize(); + ThreadSanitizerRuntime::Initialize(); + UndefinedBehaviorSanitizerRuntime::Initialize(); + MainThreadCheckerRuntime::Initialize(); + + SymbolVendorELF::Initialize(); + breakpad::SymbolFileBreakpad::Initialize(); + SymbolFileDWARF::Initialize(); + SymbolFilePDB::Initialize(); + SymbolFileSymtab::Initialize(); + UnwindAssemblyInstEmulation::Initialize(); + UnwindAssembly_x86::Initialize(); + EmulateInstructionARM64::Initialize(); + EmulateInstructionPPC64::Initialize(); + SymbolFileDWARFDebugMap::Initialize(); + ItaniumABILanguageRuntime::Initialize(); + AppleObjCRuntimeV2::Initialize(); + AppleObjCRuntimeV1::Initialize(); + SystemRuntimeMacOSX::Initialize(); + RenderScriptRuntime::Initialize(); + + CPlusPlusLanguage::Initialize(); + ObjCLanguage::Initialize(); + ObjCPlusPlusLanguage::Initialize(); + +#if defined(_WIN32) + ProcessWindows::Initialize(); +#endif +#if defined(__FreeBSD__) + ProcessFreeBSD::Initialize(); +#endif +#if defined(__APPLE__) + SymbolVendorMacOSX::Initialize(); + ProcessKDP::Initialize(); + ProcessMachCore::Initialize(); + PlatformAppleTVSimulator::Initialize(); + PlatformAppleWatchSimulator::Initialize(); + PlatformRemoteAppleTV::Initialize(); + PlatformRemoteAppleWatch::Initialize(); + DynamicLoaderDarwinKernel::Initialize(); +#endif + + // This plugin is valid on any host that talks to a Darwin remote. + // It shouldn't be limited to __APPLE__. + StructuredDataDarwinLog::Initialize(); + + // Platform agnostic plugins + platform_gdb_server::PlatformRemoteGDBServer::Initialize(); + + process_gdb_remote::ProcessGDBRemote::Initialize(); + DynamicLoaderMacOSXDYLD::Initialize(); + DynamicLoaderMacOS::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); + DynamicLoaderStatic::Initialize(); + DynamicLoaderWindowsDYLD::Initialize(); + + // Scan for any system or user LLDB plug-ins + PluginManager::Initialize(); + + // The process settings need to know about installed plug-ins, so the Settings + // must be initialized + // AFTER PluginManager::Initialize is called. + + Debugger::SettingsInitialize(); + + return llvm::Error::success(); +} + +void SystemInitializerTest::Terminate() { + static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); + Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION); + + Debugger::SettingsTerminate(); + + // Terminate and unload and loaded system or user LLDB plug-ins + PluginManager::Terminate(); + + ClangASTContext::Terminate(); + +#define LLVM_TARGET(t) LLDB_PROCESS_ ## t(Terminate) +#include "llvm/Config/Targets.def" + + DisassemblerLLVMC::Terminate(); + + JITLoaderGDB::Terminate(); + ProcessElfCore::Terminate(); + minidump::ProcessMinidump::Terminate(); + MemoryHistoryASan::Terminate(); + AddressSanitizerRuntime::Terminate(); + ThreadSanitizerRuntime::Terminate(); + UndefinedBehaviorSanitizerRuntime::Terminate(); + MainThreadCheckerRuntime::Terminate(); + SymbolVendorELF::Terminate(); + breakpad::SymbolFileBreakpad::Terminate(); + SymbolFileDWARF::Terminate(); + SymbolFilePDB::Terminate(); + SymbolFileSymtab::Terminate(); + UnwindAssembly_x86::Terminate(); + UnwindAssemblyInstEmulation::Terminate(); + EmulateInstructionARM64::Terminate(); + EmulateInstructionPPC64::Terminate(); + SymbolFileDWARFDebugMap::Terminate(); + ItaniumABILanguageRuntime::Terminate(); + AppleObjCRuntimeV2::Terminate(); + AppleObjCRuntimeV1::Terminate(); + SystemRuntimeMacOSX::Terminate(); + RenderScriptRuntime::Terminate(); + + CPlusPlusLanguage::Terminate(); + ObjCLanguage::Terminate(); + ObjCPlusPlusLanguage::Terminate(); + +#if defined(__APPLE__) + DynamicLoaderDarwinKernel::Terminate(); + ProcessMachCore::Terminate(); + ProcessKDP::Terminate(); + SymbolVendorMacOSX::Terminate(); + PlatformAppleTVSimulator::Terminate(); + PlatformAppleWatchSimulator::Terminate(); + PlatformRemoteAppleTV::Terminate(); + PlatformRemoteAppleWatch::Terminate(); +#endif + +#if defined(__FreeBSD__) + ProcessFreeBSD::Terminate(); +#endif + Debugger::SettingsTerminate(); + + platform_gdb_server::PlatformRemoteGDBServer::Terminate(); + process_gdb_remote::ProcessGDBRemote::Terminate(); + StructuredDataDarwinLog::Terminate(); + + DynamicLoaderMacOSXDYLD::Terminate(); + DynamicLoaderMacOS::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); + DynamicLoaderStatic::Terminate(); + DynamicLoaderWindowsDYLD::Terminate(); + + + platform_freebsd::PlatformFreeBSD::Terminate(); + platform_linux::PlatformLinux::Terminate(); + platform_netbsd::PlatformNetBSD::Terminate(); + platform_openbsd::PlatformOpenBSD::Terminate(); + PlatformWindows::Terminate(); + platform_android::PlatformAndroid::Terminate(); + PlatformMacOSX::Terminate(); + PlatformRemoteiOS::Terminate(); +#if defined(__APPLE__) + PlatformiOSSimulator::Terminate(); + PlatformDarwinKernel::Terminate(); +#endif + + breakpad::ObjectFileBreakpad::Terminate(); + ObjectFileELF::Terminate(); + ObjectFileMachO::Terminate(); + ObjectFilePECOFF::Terminate(); + + // Now shutdown the common parts, in reverse order. + SystemInitializerCommon::Terminate(); +} diff --git a/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.h b/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.h new file mode 100644 index 00000000000..4f58d2a64a6 --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/SystemInitializerTest.h @@ -0,0 +1,32 @@ +//===-- SystemInitializerTest.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_API_SYSTEM_INITIALIZER_TEST_H +#define LLDB_API_SYSTEM_INITIALIZER_TEST_H + +#include "lldb/Initialization/SystemInitializerCommon.h" + +namespace lldb_private { +/// Initializes lldb. +/// +/// This class is responsible for initializing all of lldb system +/// services needed to use the full LLDB application. This class is +/// not intended to be used externally, but is instead used +/// internally by SBDebugger to initialize the system. +class SystemInitializerTest : public SystemInitializerCommon { +public: + SystemInitializerTest(); + ~SystemInitializerTest() override; + + llvm::Error Initialize() override; + void Terminate() override; +}; + +} // namespace lldb_private + +#endif // LLDB_API_SYSTEM_INITIALIZER_FULL_H diff --git a/gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp b/gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp new file mode 100644 index 00000000000..66c9a87301e --- /dev/null +++ b/gnu/llvm/lldb/tools/lldb-test/lldb-test.cpp @@ -0,0 +1,1103 @@ +//===- lldb-test.cpp ------------------------------------------ *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FormatUtil.h" +#include "SystemInitializerTest.h" + +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Expression/IRMemoryMap.h" +#include "lldb/Initialization/SystemLifetimeManager.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/TypeMap.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/StreamString.h" + +#include "llvm/ADT/IntervalMap.h" +#include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/WithColor.h" + +#include <cstdio> +#include <thread> + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +namespace opts { +static cl::SubCommand BreakpointSubcommand("breakpoints", + "Test breakpoint resolution"); +cl::SubCommand ObjectFileSubcommand("object-file", + "Display LLDB object file information"); +cl::SubCommand SymbolsSubcommand("symbols", "Dump symbols for an object file"); +cl::SubCommand IRMemoryMapSubcommand("ir-memory-map", "Test IRMemoryMap"); + +cl::opt<std::string> Log("log", cl::desc("Path to a log file"), cl::init(""), + cl::sub(BreakpointSubcommand), + cl::sub(ObjectFileSubcommand), + cl::sub(SymbolsSubcommand), + cl::sub(IRMemoryMapSubcommand)); + +/// Create a target using the file pointed to by \p Filename, or abort. +TargetSP createTarget(Debugger &Dbg, const std::string &Filename); + +/// Read \p Filename into a null-terminated buffer, or abort. +std::unique_ptr<MemoryBuffer> openFile(const std::string &Filename); + +namespace breakpoint { +static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"), + cl::Required, cl::sub(BreakpointSubcommand)); +static cl::opt<std::string> CommandFile(cl::Positional, + cl::desc("<command-file>"), + cl::init("-"), + cl::sub(BreakpointSubcommand)); +static cl::opt<bool> Persistent( + "persistent", + cl::desc("Don't automatically remove all breakpoints before each command"), + cl::sub(BreakpointSubcommand)); + +static llvm::StringRef plural(uintmax_t value) { return value == 1 ? "" : "s"; } +static void dumpState(const BreakpointList &List, LinePrinter &P); +static std::string substitute(StringRef Cmd); +static int evaluateBreakpoints(Debugger &Dbg); +} // namespace breakpoint + +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::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, +}; +static cl::opt<FindType> Find( + "find", cl::desc("Choose search type:"), + 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.")), + cl::sub(SymbolsSubcommand)); + +static cl::opt<std::string> Name("name", cl::desc("Name to find."), + cl::sub(SymbolsSubcommand)); +static cl::opt<bool> + Regex("regex", + cl::desc("Search using regular expressions (avaliable for variables " + "and functions only)."), + cl::sub(SymbolsSubcommand)); +static cl::opt<std::string> + Context("context", + cl::desc("Restrict search to the context of the given variable."), + cl::value_desc("variable"), cl::sub(SymbolsSubcommand)); + +static cl::opt<std::string> CompilerContext( + "compiler-context", + cl::desc("Specify a compiler context as \"kind:name,...\"."), + cl::value_desc("context"), cl::sub(SymbolsSubcommand)); + +static cl::opt<std::string> + Language("language", cl::desc("Specify a language type, like C99."), + cl::value_desc("language"), cl::sub(SymbolsSubcommand)); + +static cl::list<FunctionNameType> FunctionNameFlags( + "function-flags", cl::desc("Function search flags:"), + cl::values(clEnumValN(eFunctionNameTypeAuto, "auto", + "Automatically deduce flags based on name."), + clEnumValN(eFunctionNameTypeFull, "full", "Full function name."), + clEnumValN(eFunctionNameTypeBase, "base", "Base name."), + clEnumValN(eFunctionNameTypeMethod, "method", "Method name."), + clEnumValN(eFunctionNameTypeSelector, "selector", + "Selector name.")), + cl::sub(SymbolsSubcommand)); +static FunctionNameType getFunctionNameFlags() { + FunctionNameType Result = FunctionNameType(0); + for (FunctionNameType Flag : FunctionNameFlags) + Result = FunctionNameType(Result | Flag); + return Result; +} + +static cl::opt<bool> DumpAST("dump-ast", + cl::desc("Dump AST restored from symbols."), + cl::sub(SymbolsSubcommand)); +static cl::opt<bool> + DumpClangAST("dump-clang-ast", + cl::desc("Dump clang AST restored from symbols."), + cl::sub(SymbolsSubcommand)); + +static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."), + cl::sub(SymbolsSubcommand)); + +static cl::opt<std::string> File("file", + cl::desc("File (compile unit) to search."), + cl::sub(SymbolsSubcommand)); +static cl::opt<int> Line("line", cl::desc("Line to search."), + cl::sub(SymbolsSubcommand)); + +static Expected<CompilerDeclContext> getDeclContext(SymbolFile &Symfile); + +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 dumpClangAST(lldb_private::Module &Module); +static Error verify(lldb_private::Module &Module); + +static Expected<Error (*)(lldb_private::Module &)> getAction(); +static int dumpSymbols(Debugger &Dbg); +} // namespace symbols + +namespace irmemorymap { +static cl::opt<std::string> Target(cl::Positional, cl::desc("<target>"), + cl::Required, + cl::sub(IRMemoryMapSubcommand)); +static cl::opt<std::string> CommandFile(cl::Positional, + cl::desc("<command-file>"), + cl::init("-"), + cl::sub(IRMemoryMapSubcommand)); +static cl::opt<bool> UseHostOnlyAllocationPolicy( + "host-only", cl::desc("Use the host-only allocation policy"), + cl::init(false), cl::sub(IRMemoryMapSubcommand)); + +using AllocationT = std::pair<addr_t, addr_t>; +using AddrIntervalMap = + IntervalMap<addr_t, unsigned, 8, IntervalMapHalfOpenInfo<addr_t>>; + +struct IRMemoryMapTestState { + TargetSP Target; + IRMemoryMap Map; + + AddrIntervalMap::Allocator IntervalMapAllocator; + AddrIntervalMap Allocations; + + StringMap<addr_t> Label2AddrMap; + + IRMemoryMapTestState(TargetSP Target) + : Target(Target), Map(Target), Allocations(IntervalMapAllocator) {} +}; + +bool evalMalloc(StringRef Line, IRMemoryMapTestState &State); +bool evalFree(StringRef Line, IRMemoryMapTestState &State); +int evaluateMemoryMapCommands(Debugger &Dbg); +} // namespace irmemorymap + +} // namespace opts + +std::vector<CompilerContext> parseCompilerContext() { + std::vector<CompilerContext> result; + if (opts::symbols::CompilerContext.empty()) + return result; + + StringRef str{opts::symbols::CompilerContext}; + SmallVector<StringRef, 8> entries_str; + str.split(entries_str, ',', /*maxSplit*/-1, /*keepEmpty=*/false); + for (auto entry_str : entries_str) { + StringRef key, value; + std::tie(key, value) = entry_str.split(':'); + auto kind = + StringSwitch<CompilerContextKind>(key) + .Case("TranslationUnit", CompilerContextKind::TranslationUnit) + .Case("Module", CompilerContextKind::Module) + .Case("Namespace", CompilerContextKind::Namespace) + .Case("Class", CompilerContextKind::Class) + .Case("Struct", CompilerContextKind::Struct) + .Case("Union", CompilerContextKind::Union) + .Case("Function", CompilerContextKind::Function) + .Case("Variable", CompilerContextKind::Variable) + .Case("Enum", CompilerContextKind::Enum) + .Case("Typedef", CompilerContextKind::Typedef) + .Case("AnyModule", CompilerContextKind::AnyModule) + .Case("AnyType", CompilerContextKind::AnyType) + .Default(CompilerContextKind::Invalid); + if (value.empty()) { + WithColor::error() << "compiler context entry has no \"name\"\n"; + exit(1); + } + result.push_back({kind, ConstString{value}}); + } + outs() << "Search context: {\n"; + for (auto entry: result) + entry.Dump(); + outs() << "}\n"; + + return result; +} + +template <typename... Args> +static Error make_string_error(const char *Format, Args &&... args) { + return llvm::make_error<llvm::StringError>( + llvm::formatv(Format, std::forward<Args>(args)...).str(), + llvm::inconvertibleErrorCode()); +} + +TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) { + TargetSP 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); + } + return Target; +} + +std::unique_ptr<MemoryBuffer> opts::openFile(const std::string &Filename) { + auto MB = MemoryBuffer::getFileOrSTDIN(Filename); + if (!MB) { + errs() << formatv("Could not open file '{0}: {1}\n", Filename, + MB.getError().message()); + exit(1); + } + return std::move(*MB); +} + +void opts::breakpoint::dumpState(const BreakpointList &List, LinePrinter &P) { + P.formatLine("{0} breakpoint{1}", List.GetSize(), plural(List.GetSize())); + if (List.GetSize() > 0) + P.formatLine("At least one breakpoint."); + for (size_t i = 0, e = List.GetSize(); i < e; ++i) { + BreakpointSP BP = List.GetBreakpointAtIndex(i); + P.formatLine("Breakpoint ID {0}:", BP->GetID()); + AutoIndent Indent(P, 2); + P.formatLine("{0} location{1}.", BP->GetNumLocations(), + plural(BP->GetNumLocations())); + if (BP->GetNumLocations() > 0) + P.formatLine("At least one location."); + P.formatLine("{0} resolved location{1}.", BP->GetNumResolvedLocations(), + plural(BP->GetNumResolvedLocations())); + if (BP->GetNumResolvedLocations() > 0) + P.formatLine("At least one resolved location."); + for (size_t l = 0, le = BP->GetNumLocations(); l < le; ++l) { + BreakpointLocationSP Loc = BP->GetLocationAtIndex(l); + P.formatLine("Location ID {0}:", Loc->GetID()); + AutoIndent Indent(P, 2); + P.formatLine("Enabled: {0}", Loc->IsEnabled()); + P.formatLine("Resolved: {0}", Loc->IsResolved()); + SymbolContext sc; + Loc->GetAddress().CalculateSymbolContext(&sc); + lldb_private::StreamString S; + sc.DumpStopContext(&S, BP->GetTarget().GetProcessSP().get(), + Loc->GetAddress(), false, true, false, true, true); + P.formatLine("Address: {0}", S.GetString()); + } + } + P.NewLine(); +} + +std::string opts::breakpoint::substitute(StringRef Cmd) { + std::string Result; + raw_string_ostream OS(Result); + while (!Cmd.empty()) { + switch (Cmd[0]) { + case '%': + if (Cmd.consume_front("%p") && (Cmd.empty() || !isalnum(Cmd[0]))) { + OS << sys::path::parent_path(breakpoint::CommandFile); + break; + } + LLVM_FALLTHROUGH; + default: + size_t pos = Cmd.find('%'); + OS << Cmd.substr(0, pos); + Cmd = Cmd.substr(pos); + break; + } + } + return std::move(OS.str()); +} + +int opts::breakpoint::evaluateBreakpoints(Debugger &Dbg) { + TargetSP Target = opts::createTarget(Dbg, breakpoint::Target); + std::unique_ptr<MemoryBuffer> MB = opts::openFile(breakpoint::CommandFile); + + LinePrinter P(4, outs()); + StringRef Rest = MB->getBuffer(); + int HadErrors = 0; + while (!Rest.empty()) { + StringRef Line; + std::tie(Line, Rest) = Rest.split('\n'); + Line = Line.ltrim().rtrim(); + if (Line.empty() || Line[0] == '#') + continue; + + if (!Persistent) + Target->RemoveAllBreakpoints(/*internal_also*/ true); + + std::string Command = substitute(Line); + P.formatLine("Command: {0}", Command); + CommandReturnObject Result; + if (!Dbg.GetCommandInterpreter().HandleCommand( + Command.c_str(), /*add_to_history*/ eLazyBoolNo, Result)) { + P.formatLine("Failed: {0}", Result.GetErrorData()); + HadErrors = 1; + continue; + } + + dumpState(Target->GetBreakpointList(/*internal*/ false), P); + } + return HadErrors; +} + +Expected<CompilerDeclContext> +opts::symbols::getDeclContext(SymbolFile &Symfile) { + if (Context.empty()) + return CompilerDeclContext(); + VariableList List; + Symfile.FindGlobalVariables(ConstString(Context), nullptr, UINT32_MAX, List); + if (List.Empty()) + return make_string_error("Context search didn't find a match."); + if (List.GetSize() > 1) + return make_string_error("Context search found multiple matches."); + return List.GetVariableAtIndex(0)->GetDeclContext(); +} + +Error opts::symbols::findFunctions(lldb_private::Module &Module) { + SymbolFile &Symfile = *Module.GetSymbolFile(); + SymbolContextList List; + if (!File.empty()) { + assert(Line != 0); + + 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; + const bool include_inlined_functions = false; + auto addr = + le.GetSameLineContiguousAddressRange(include_inlined_functions) + .GetBaseAddress(); + if (!addr.IsValid()) + continue; + + SymbolContext sc; + uint32_t resolved = + addr.CalculateSymbolContext(&sc, eSymbolContextFunction); + if (resolved & eSymbolContextFunction) + List.Append(sc); + } + } else if (Regex) { + RegularExpression RE(Name); + assert(RE.IsValid()); + List.Clear(); + Symfile.FindFunctions(RE, true, List); + } else { + Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); + if (!ContextOr) + return ContextOr.takeError(); + CompilerDeclContext *ContextPtr = + ContextOr->IsValid() ? &*ContextOr : nullptr; + + List.Clear(); + Symfile.FindFunctions(ConstString(Name), ContextPtr, getFunctionNameFlags(), + true, List); + } + outs() << formatv("Found {0} functions:\n", List.GetSize()); + StreamString Stream; + List.Dump(&Stream, nullptr); + outs() << Stream.GetData() << "\n"; + 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; + const bool include_inlined_functions = false; + auto addr = le.GetSameLineContiguousAddressRange(include_inlined_functions) + .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) { + SymbolFile &Symfile = *Module.GetSymbolFile(); + Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); + if (!ContextOr) + return ContextOr.takeError(); + CompilerDeclContext *ContextPtr = + ContextOr->IsValid() ? &*ContextOr : nullptr; + + CompilerDeclContext Result = + Symfile.FindNamespace(ConstString(Name), ContextPtr); + if (Result) + outs() << "Found namespace: " + << Result.GetScopeQualifiedName().GetStringRef() << "\n"; + else + outs() << "Namespace not found.\n"; + return Error::success(); +} + +Error opts::symbols::findTypes(lldb_private::Module &Module) { + SymbolFile &Symfile = *Module.GetSymbolFile(); + Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); + if (!ContextOr) + return ContextOr.takeError(); + CompilerDeclContext *ContextPtr = + ContextOr->IsValid() ? &*ContextOr : nullptr; + + LanguageSet languages; + if (!Language.empty()) + languages.Insert(Language::GetLanguageTypeFromString(Language)); + + DenseSet<SymbolFile *> SearchedFiles; + TypeMap Map; + if (!Name.empty()) + Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles, + Map); + else + Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map); + + outs() << formatv("Found {0} types:\n", Map.GetSize()); + StreamString Stream; + Map.Dump(&Stream, false); + outs() << Stream.GetData() << "\n"; + return Error::success(); +} + +Error opts::symbols::findVariables(lldb_private::Module &Module) { + SymbolFile &Symfile = *Module.GetSymbolFile(); + VariableList List; + if (Regex) { + RegularExpression RE(Name); + assert(RE.IsValid()); + Symfile.FindGlobalVariables(RE, UINT32_MAX, List); + } else if (!File.empty()) { + CompUnitSP CU; + for (size_t Ind = 0; !CU && Ind < Module.GetNumCompileUnits(); ++Ind) { + CompUnitSP Candidate = Module.GetCompileUnitAtIndex(Ind); + if (!Candidate || + Candidate->GetPrimaryFile().GetFilename().GetStringRef() != File) + continue; + if (CU) + return make_string_error("Multiple compile units for file `{0}` found.", + File); + CU = std::move(Candidate); + } + + if (!CU) + return make_string_error("Compile unit `{0}` not found.", File); + + List.AddVariables(CU->GetVariableList(true).get()); + } else { + Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); + if (!ContextOr) + return ContextOr.takeError(); + CompilerDeclContext *ContextPtr = + ContextOr->IsValid() ? &*ContextOr : nullptr; + + Symfile.FindGlobalVariables(ConstString(Name), ContextPtr, UINT32_MAX, List); + } + outs() << formatv("Found {0} variables:\n", List.GetSize()); + StreamString Stream; + List.Dump(&Stream, false); + outs() << Stream.GetData() << "\n"; + return Error::success(); +} + +Error opts::symbols::dumpModule(lldb_private::Module &Module) { + StreamString Stream; + Module.ParseAllDebugSymbols(); + Module.Dump(&Stream); + outs() << Stream.GetData() << "\n"; + return Error::success(); +} + +Error opts::symbols::dumpAST(lldb_private::Module &Module) { + Module.ParseAllDebugSymbols(); + + SymbolFile *symfile = Module.GetSymbolFile(); + if (!symfile) + return make_string_error("Module has no symbol file."); + + llvm::Expected<TypeSystem &> type_system_or_err = + symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); + if (!type_system_or_err) + return make_string_error("Can't retrieve ClangASTContext"); + + auto *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_ast_ctx) + return make_string_error("Retrieved TypeSystem was not a ClangASTContext"); + + clang::ASTContext &ast_ctx = clang_ast_ctx->getASTContext(); + + clang::TranslationUnitDecl *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::dumpClangAST(lldb_private::Module &Module) { + Module.ParseAllDebugSymbols(); + + SymbolFile *symfile = Module.GetSymbolFile(); + if (!symfile) + return make_string_error("Module has no symbol file."); + + llvm::Expected<TypeSystem &> type_system_or_err = + symfile->GetTypeSystemForLanguage(eLanguageTypeObjC_plus_plus); + if (!type_system_or_err) + return make_string_error("Can't retrieve ClangASTContext"); + + auto *clang_ast_ctx = + llvm::dyn_cast_or_null<ClangASTContext>(&type_system_or_err.get()); + if (!clang_ast_ctx) + return make_string_error("Retrieved TypeSystem was not a ClangASTContext"); + + StreamString Stream; + clang_ast_ctx->DumpFromSymbolFile(Stream, Name); + outs() << Stream.GetData() << "\n"; + + return Error::success(); +} + +Error opts::symbols::verify(lldb_private::Module &Module) { + SymbolFile *symfile = Module.GetSymbolFile(); + if (!symfile) + return make_string_error("Module has no symbol file."); + + uint32_t comp_units_count = symfile->GetNumCompileUnits(); + + outs() << "Found " << comp_units_count << " compile units.\n"; + + for (uint32_t i = 0; i < comp_units_count; i++) { + lldb::CompUnitSP comp_unit = symfile->GetCompileUnitAtIndex(i); + if (!comp_unit) + return make_string_error("Connot parse compile unit {0}.", i); + + outs() << "Processing '" + << comp_unit->GetPrimaryFile().GetFilename().AsCString() + << "' compile unit.\n"; + + LineTable *lt = comp_unit->GetLineTable(); + if (!lt) + return make_string_error("Can't get a line table of a compile unit."); + + uint32_t count = lt->GetSize(); + + outs() << "The line table contains " << count << " entries.\n"; + + if (count == 0) + continue; + + LineEntry le; + if (!lt->GetLineEntryAtIndex(0, le)) + return make_string_error("Can't get a line entry of a compile unit."); + + for (uint32_t i = 1; i < count; i++) { + lldb::addr_t curr_end = + le.range.GetBaseAddress().GetFileAddress() + le.range.GetByteSize(); + + if (!lt->GetLineEntryAtIndex(i, le)) + return make_string_error("Can't get a line entry of a compile unit"); + + if (curr_end > le.range.GetBaseAddress().GetFileAddress()) + return make_string_error( + "Line table of a compile unit is inconsistent."); + } + } + + outs() << "The symbol information is verified.\n"; + + return Error::success(); +} + +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( + "Cannot both search and verify symbol information."); + 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 symbol verification."); + 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 (DumpClangAST) { + if (Find != FindType::None) + return make_string_error("Cannot both search and dump clang AST."); + if (Regex || !Context.empty() || !File.empty() || Line != 0) + return make_string_error( + "-regex, -context, -name, -file and -line options are not " + "applicable for dumping clang AST."); + return dumpClangAST; + } + + if (Regex && !Context.empty()) + return make_string_error( + "Cannot search using both regular expressions and context."); + + if (Regex && !RegularExpression(Name).IsValid()) + return make_string_error("`{0}` is not a valid regular expression.", Name); + + if (Regex + !Context.empty() + !File.empty() >= 2) + return make_string_error( + "Only one of -regex, -context and -file may be used simultaneously."); + if (Regex && Name.empty()) + return make_string_error("-regex used without a -name"); + + switch (Find) { + case FindType::None: + if (!Context.empty() || !Name.empty() || !File.empty() || Line != 0) + return make_string_error( + "Specify search type (-find) to use search options."); + return dumpModule; + + case FindType::Function: + if (!File.empty() + (Line != 0) == 1) + return make_string_error("Both file name and line number must be " + "specified when searching a function " + "by file position."); + if (Regex + (getFunctionNameFlags() != 0) + !File.empty() >= 2) + return make_string_error("Only one of regular expression, function-flags " + "and file position may be used simultaneously " + "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 " + "expressions, file names or line numbers."); + return findNamespaces; + + case FindType::Type: + if (Regex || !File.empty() || Line != 0) + return make_string_error("Cannot search for types using regular " + "expressions, file names or line numbers."); + if (!Name.empty() && !CompilerContext.empty()) + return make_string_error("Name is ignored if compiler context present."); + + return findTypes; + + case FindType::Variable: + if (Line != 0) + return make_string_error("Cannot search for variables " + "using line numbers."); + return findVariables; + } + + llvm_unreachable("Unsupported symbol action."); +} + +int opts::symbols::dumpSymbols(Debugger &Dbg) { + auto ActionOr = getAction(); + if (!ActionOr) { + logAllUnhandledErrors(ActionOr.takeError(), WithColor::error(), ""); + return 1; + } + auto Action = *ActionOr; + + 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); + SymbolFile *Symfile = ModulePtr->GetSymbolFile(); + if (!Symfile) { + WithColor::error() << "Module has no symbol vendor.\n"; + return 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) { + lldb_private::DataExtractor Data; + S->GetSectionData(Data); + ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()}; + Printer.formatBinary("Data: ", Bytes, 0); + } + + if (S->GetType() == eSectionTypeContainer) + dumpSectionList(Printer, S->GetChildren(), true); + Printer.NewLine(); + } +} + +static int dumpObjectFiles(Debugger &Dbg) { + LinePrinter Printer(4, llvm::outs()); + + int HadErrors = 0; + for (const auto &File : opts::object::InputFilenames) { + 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->GetSymbolFile(); + SectionList *Sections = ModulePtr->GetSectionList(); + if (!Sections) { + llvm::errs() << "Could not load sections for module " << File << "\n"; + HadErrors = 1; + continue; + } + + Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName()); + Printer.formatLine("Architecture: {0}", + ModulePtr->GetArchitecture().GetTriple().getTriple()); + Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString()); + 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(); + } + } + return HadErrors; +} + +bool opts::irmemorymap::evalMalloc(StringRef Line, + IRMemoryMapTestState &State) { + // ::= <label> = malloc <size> <alignment> + StringRef Label; + std::tie(Label, Line) = Line.split('='); + if (Line.empty()) + return false; + Label = Label.trim(); + Line = Line.trim(); + size_t Size; + uint8_t Alignment; + int Matches = sscanf(Line.data(), "malloc %zu %hhu", &Size, &Alignment); + if (Matches != 2) + return false; + + outs() << formatv("Command: {0} = malloc(size={1}, alignment={2})\n", Label, + Size, Alignment); + if (!isPowerOf2_32(Alignment)) { + outs() << "Malloc error: alignment is not a power of 2\n"; + exit(1); + } + + IRMemoryMap::AllocationPolicy AP = + UseHostOnlyAllocationPolicy ? IRMemoryMap::eAllocationPolicyHostOnly + : IRMemoryMap::eAllocationPolicyProcessOnly; + + // Issue the malloc in the target process with "-rw" permissions. + const uint32_t Permissions = 0x3; + const bool ZeroMemory = false; + Status ST; + addr_t Addr = + State.Map.Malloc(Size, Alignment, Permissions, AP, ZeroMemory, ST); + if (ST.Fail()) { + outs() << formatv("Malloc error: {0}\n", ST); + return true; + } + + // Print the result of the allocation before checking its validity. + outs() << formatv("Malloc: address = {0:x}\n", Addr); + + // Check that the allocation is aligned. + if (!Addr || Addr % Alignment != 0) { + outs() << "Malloc error: zero or unaligned allocation detected\n"; + exit(1); + } + + // 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. + static unsigned AllocationID = 0; + State.Allocations.insert(Addr, EndOfRegion, AllocationID++); + + // Store the label -> address mapping. + State.Label2AddrMap[Label] = Addr; + + return true; +} + +bool opts::irmemorymap::evalFree(StringRef Line, IRMemoryMapTestState &State) { + // ::= free <label> + if (!Line.consume_front("free")) + return false; + StringRef Label = Line.trim(); + + outs() << formatv("Command: free({0})\n", Label); + auto LabelIt = State.Label2AddrMap.find(Label); + if (LabelIt == State.Label2AddrMap.end()) { + outs() << "Free error: Invalid allocation label\n"; + exit(1); + } + + Status ST; + addr_t Addr = LabelIt->getValue(); + State.Map.Free(Addr, ST); + if (ST.Fail()) { + outs() << formatv("Free error: {0}\n", ST); + exit(1); + } + + // Erase the allocation from the live interval map. + auto Interval = State.Allocations.find(Addr); + if (Interval != State.Allocations.end()) { + outs() << formatv("Free: [{0:x}, {1:x})\n", Interval.start(), + Interval.stop()); + Interval.erase(); + } + + return true; +} + +int opts::irmemorymap::evaluateMemoryMapCommands(Debugger &Dbg) { + // Set up a Target. + TargetSP Target = opts::createTarget(Dbg, irmemorymap::Target); + + // Set up a Process. In order to allocate memory within a target, this + // process must be alive and must support JIT'ing. + CommandReturnObject Result; + Dbg.SetAsyncExecution(false); + CommandInterpreter &CI = Dbg.GetCommandInterpreter(); + auto IssueCmd = [&](const char *Cmd) -> bool { + return CI.HandleCommand(Cmd, eLazyBoolNo, Result); + }; + if (!IssueCmd("b main") || !IssueCmd("run")) { + outs() << formatv("Failed: {0}\n", Result.GetErrorData()); + exit(1); + } + + ProcessSP Process = Target->GetProcessSP(); + if (!Process || !Process->IsAlive() || !Process->CanJIT()) { + outs() << "Cannot use process to test IRMemoryMap\n"; + exit(1); + } + + // Set up an IRMemoryMap and associated testing state. + IRMemoryMapTestState State(Target); + + // Parse and apply commands from the command file. + std::unique_ptr<MemoryBuffer> MB = opts::openFile(irmemorymap::CommandFile); + StringRef Rest = MB->getBuffer(); + while (!Rest.empty()) { + StringRef Line; + std::tie(Line, Rest) = Rest.split('\n'); + Line = Line.ltrim().rtrim(); + + if (Line.empty() || Line[0] == '#') + continue; + + if (evalMalloc(Line, State)) + continue; + + if (evalFree(Line, State)) + continue; + + errs() << "Could not parse line: " << Line << "\n"; + exit(1); + } + return 0; +} + +int main(int argc, const char *argv[]) { + StringRef ToolName = argv[0]; + sys::PrintStackTraceOnErrorSignal(ToolName); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; + + cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n"); + + SystemLifetimeManager DebuggerLifetime; + if (auto e = DebuggerLifetime.Initialize( + std::make_unique<SystemInitializerTest>(), nullptr)) { + WithColor::error() << "initialization failed: " << toString(std::move(e)) + << '\n'; + return 1; + } + + auto TerminateDebugger = + llvm::make_scope_exit([&] { DebuggerLifetime.Terminate(); }); + + auto Dbg = lldb_private::Debugger::CreateInstance(); + ModuleList::GetGlobalModuleListProperties().SetEnableExternalLookup(false); + CommandReturnObject Result; + Dbg->GetCommandInterpreter().HandleCommand( + "settings set plugin.process.gdb-remote.packet-timeout 60", + /*add_to_history*/ eLazyBoolNo, Result); + + if (!opts::Log.empty()) + Dbg->EnableLog("lldb", {"all"}, opts::Log, 0, errs()); + + if (opts::BreakpointSubcommand) + return opts::breakpoint::evaluateBreakpoints(*Dbg); + if (opts::ObjectFileSubcommand) + return dumpObjectFiles(*Dbg); + if (opts::SymbolsSubcommand) + return opts::symbols::dumpSymbols(*Dbg); + if (opts::IRMemoryMapSubcommand) + return opts::irmemorymap::evaluateMemoryMapCommands(*Dbg); + + WithColor::error() << "No command specified.\n"; + return 1; +} |