diff options
Diffstat (limited to 'source/Plugins')
241 files changed, 0 insertions, 48909 deletions
diff --git a/source/Plugins/ABI/CMakeLists.txt b/source/Plugins/ABI/CMakeLists.txt deleted file mode 100644 index 9d7a79308d7b9..0000000000000 --- a/source/Plugins/ABI/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_subdirectory(SysV-arm) -add_subdirectory(SysV-arm64) -add_subdirectory(SysV-hexagon) -add_subdirectory(SysV-ppc) -add_subdirectory(SysV-ppc64) -add_subdirectory(SysV-mips) -add_subdirectory(SysV-mips64) -add_subdirectory(SysV-s390x) -add_subdirectory(SysV-i386) -add_subdirectory(SysV-x86_64) -add_subdirectory(MacOSX-i386) -add_subdirectory(MacOSX-arm) -add_subdirectory(MacOSX-arm64) diff --git a/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt b/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt deleted file mode 100644 index b41814f3237b5..0000000000000 --- a/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginABIMacOSX_arm PLUGIN - ABIMacOSX_arm.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/MacOSX-arm64/CMakeLists.txt b/source/Plugins/ABI/MacOSX-arm64/CMakeLists.txt deleted file mode 100644 index f769d63bcdacf..0000000000000 --- a/source/Plugins/ABI/MacOSX-arm64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABIMacOSX_arm64 PLUGIN - ABIMacOSX_arm64.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt b/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt deleted file mode 100644 index 21f153d36e084..0000000000000 --- a/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABIMacOSX_i386 PLUGIN - ABIMacOSX_i386.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-arm/CMakeLists.txt b/source/Plugins/ABI/SysV-arm/CMakeLists.txt deleted file mode 100644 index c5979046d36cb..0000000000000 --- a/source/Plugins/ABI/SysV-arm/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginABISysV_arm PLUGIN - ABISysV_arm.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-arm64/CMakeLists.txt b/source/Plugins/ABI/SysV-arm64/CMakeLists.txt deleted file mode 100644 index 077b394823c6d..0000000000000 --- a/source/Plugins/ABI/SysV-arm64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_arm64 PLUGIN - ABISysV_arm64.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-hexagon/CMakeLists.txt b/source/Plugins/ABI/SysV-hexagon/CMakeLists.txt deleted file mode 100644 index a857fff12399e..0000000000000 --- a/source/Plugins/ABI/SysV-hexagon/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_hexagon PLUGIN - ABISysV_hexagon.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-i386/CMakeLists.txt b/source/Plugins/ABI/SysV-i386/CMakeLists.txt deleted file mode 100644 index 598b3d03c0f39..0000000000000 --- a/source/Plugins/ABI/SysV-i386/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_i386 PLUGIN - ABISysV_i386.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-mips/CMakeLists.txt b/source/Plugins/ABI/SysV-mips/CMakeLists.txt deleted file mode 100644 index a3266a75ae738..0000000000000 --- a/source/Plugins/ABI/SysV-mips/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_mips PLUGIN - ABISysV_mips.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-mips64/CMakeLists.txt b/source/Plugins/ABI/SysV-mips64/CMakeLists.txt deleted file mode 100644 index 5eddfb539f051..0000000000000 --- a/source/Plugins/ABI/SysV-mips64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_mips64 PLUGIN - ABISysV_mips64.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-ppc/CMakeLists.txt b/source/Plugins/ABI/SysV-ppc/CMakeLists.txt deleted file mode 100644 index 63bfc4a96cdf4..0000000000000 --- a/source/Plugins/ABI/SysV-ppc/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_ppc PLUGIN - ABISysV_ppc.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt b/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt deleted file mode 100644 index b31182dd0f78e..0000000000000 --- a/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_ppc64 PLUGIN - ABISysV_ppc64.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-s390x/CMakeLists.txt b/source/Plugins/ABI/SysV-s390x/CMakeLists.txt deleted file mode 100644 index f670f0157a6be..0000000000000 --- a/source/Plugins/ABI/SysV-s390x/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_s390x PLUGIN - ABISysV_s390x.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt b/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt deleted file mode 100644 index 17644d74ac2f3..0000000000000 --- a/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginABISysV_x86_64 PLUGIN - ABISysV_x86_64.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Architecture/Arm/CMakeLists.txt b/source/Plugins/Architecture/Arm/CMakeLists.txt deleted file mode 100644 index 60bbe69a99fbf..0000000000000 --- a/source/Plugins/Architecture/Arm/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginArchitectureArm PLUGIN - ArchitectureArm.cpp - - LINK_LIBS - lldbPluginProcessUtility - lldbCore - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Architecture/CMakeLists.txt b/source/Plugins/Architecture/CMakeLists.txt deleted file mode 100644 index 14ad91644595a..0000000000000 --- a/source/Plugins/Architecture/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_subdirectory(Arm) -add_subdirectory(Mips) -add_subdirectory(PPC64) diff --git a/source/Plugins/Architecture/Mips/CMakeLists.txt b/source/Plugins/Architecture/Mips/CMakeLists.txt deleted file mode 100644 index 9734edc6b12bb..0000000000000 --- a/source/Plugins/Architecture/Mips/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginArchitectureMips PLUGIN - ArchitectureMips.cpp - - LINK_LIBS - lldbCore - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Architecture/PPC64/CMakeLists.txt b/source/Plugins/Architecture/PPC64/CMakeLists.txt deleted file mode 100644 index 2cba112cf8827..0000000000000 --- a/source/Plugins/Architecture/PPC64/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginArchitecturePPC64 PLUGIN - ArchitecturePPC64.cpp - - LINK_LIBS - lldbPluginProcessUtility - lldbCore - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/CMakeLists.txt b/source/Plugins/CMakeLists.txt deleted file mode 100644 index 5092b210a12cf..0000000000000 --- a/source/Plugins/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -add_subdirectory(ABI) -add_subdirectory(Architecture) -add_subdirectory(Disassembler) -add_subdirectory(DynamicLoader) -add_subdirectory(ExpressionParser) -add_subdirectory(Instruction) -add_subdirectory(InstrumentationRuntime) -add_subdirectory(JITLoader) -add_subdirectory(Language) -add_subdirectory(LanguageRuntime) -add_subdirectory(MemoryHistory) -add_subdirectory(ObjectContainer) -add_subdirectory(ObjectFile) -add_subdirectory(OperatingSystem) -add_subdirectory(Platform) -add_subdirectory(Process) -add_subdirectory(ScriptInterpreter) -add_subdirectory(StructuredData) -add_subdirectory(SymbolFile) -add_subdirectory(SystemRuntime) -add_subdirectory(SymbolVendor) -add_subdirectory(UnwindAssembly) diff --git a/source/Plugins/Disassembler/CMakeLists.txt b/source/Plugins/Disassembler/CMakeLists.txt deleted file mode 100644 index 6e3c904d5a605..0000000000000 --- a/source/Plugins/Disassembler/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(llvm) diff --git a/source/Plugins/Disassembler/llvm/CMakeLists.txt b/source/Plugins/Disassembler/llvm/CMakeLists.txt deleted file mode 100644 index a25a436d498e1..0000000000000 --- a/source/Plugins/Disassembler/llvm/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_lldb_library(lldbPluginDisassemblerLLVM PLUGIN - DisassemblerLLVMC.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} - MC - MCDisassembler - RuntimeDyld - Support - ) diff --git a/source/Plugins/DynamicLoader/CMakeLists.txt b/source/Plugins/DynamicLoader/CMakeLists.txt deleted file mode 100644 index 9f3b2ab0e50fd..0000000000000 --- a/source/Plugins/DynamicLoader/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_subdirectory(Darwin-Kernel) -add_subdirectory(MacOSX-DYLD) -add_subdirectory(POSIX-DYLD) -add_subdirectory(Static) -add_subdirectory(Hexagon-DYLD) -add_subdirectory(Windows-DYLD) diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt b/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt deleted file mode 100644 index ffc797b7475bf..0000000000000 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderDarwinKernel PLUGIN - DynamicLoaderDarwinKernel.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginPlatformMacOSX - ) diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp deleted file mode 100644 index 3a80c68dd4d71..0000000000000 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ /dev/null @@ -1,1583 +0,0 @@ -//===-- DynamicLoaderDarwinKernel.cpp -----------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Host/Symbols.h" -#include "lldb/Interpreter/OptionValueProperties.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/OperatingSystem.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" - -#include "DynamicLoaderDarwinKernel.h" - -//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#include <stdio.h> -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif - -using namespace lldb; -using namespace lldb_private; - -// Progressively greater amounts of scanning we will allow For some targets -// very early in startup, we can't do any random reads of memory or we can -// crash the device so a setting is needed that can completely disable the -// KASLR scans. - -enum KASLRScanType { - eKASLRScanNone = 0, // No reading into the inferior at all - eKASLRScanLowgloAddresses, // Check one word of memory for a possible kernel - // addr, then see if a kernel is there - eKASLRScanNearPC, // Scan backwards from the current $pc looking for kernel; - // checking at 96 locations total - eKASLRScanExhaustiveScan // Scan through the entire possible kernel address - // range looking for a kernel -}; - -static constexpr OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = { - {eKASLRScanNone, "none", - "Do not read memory looking for a Darwin kernel when attaching."}, - {eKASLRScanLowgloAddresses, "basic", "Check for the Darwin kernel's load " - "addr in the lowglo page " - "(boot-args=debug) only."}, - {eKASLRScanNearPC, "fast-scan", "Scan near the pc value on attach to find " - "the Darwin kernel's load address."}, - {eKASLRScanExhaustiveScan, "exhaustive-scan", - "Scan through the entire potential address range of Darwin kernel (only " - "on 32-bit targets)."}}; - -static constexpr PropertyDefinition g_properties[] = { - {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, {}, - "Automatically loads kext images when attaching to a kernel."}, - {"scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, NULL, - OptionEnumValues(g_kaslr_kernel_scan_enum_values), - "Control how many reads lldb will make while searching for a Darwin " - "kernel on attach."}}; - -enum { ePropertyLoadKexts, ePropertyScanType }; - -class DynamicLoaderDarwinKernelProperties : public Properties { -public: - static ConstString &GetSettingName() { - static ConstString g_setting_name("darwin-kernel"); - return g_setting_name; - } - - DynamicLoaderDarwinKernelProperties() : Properties() { - m_collection_sp.reset(new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } - - virtual ~DynamicLoaderDarwinKernelProperties() {} - - bool GetLoadKexts() const { - const uint32_t idx = ePropertyLoadKexts; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - NULL, idx, g_properties[idx].default_uint_value != 0); - } - - KASLRScanType GetScanType() const { - const uint32_t idx = ePropertyScanType; - return (KASLRScanType)m_collection_sp->GetPropertyAtIndexAsEnumeration( - NULL, idx, g_properties[idx].default_uint_value); - } -}; - -typedef std::shared_ptr<DynamicLoaderDarwinKernelProperties> - DynamicLoaderDarwinKernelPropertiesSP; - -static const DynamicLoaderDarwinKernelPropertiesSP &GetGlobalProperties() { - static DynamicLoaderDarwinKernelPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset(new DynamicLoaderDarwinKernelProperties()); - return g_settings_sp; -} - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process, - bool force) { - if (!force) { - // If the user provided an executable binary and it is not a kernel, this - // plugin should not create an instance. - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - if (object_file->GetStrata() != ObjectFile::eStrataKernel) { - return NULL; - } - } - } - - // If the target's architecture does not look like an Apple environment, - // this plugin should not create an instance. - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - if (triple_ref.getVendor() != llvm::Triple::Apple) { - return NULL; - } - break; - // If we have triple like armv7-unknown-unknown, we should try looking for - // a Darwin kernel. - case llvm::Triple::UnknownOS: - break; - default: - return NULL; - break; - } - } - - // At this point if there is an ExecutableModule, it is a kernel and the - // Target is some variant of an Apple system. If the Process hasn't provided - // the kernel load address, we need to look around in memory to find it. - - const addr_t kernel_load_address = SearchForDarwinKernel(process); - if (CheckForKernelImageAtAddress(kernel_load_address, process).IsValid()) { - process->SetCanRunCode(false); - return new DynamicLoaderDarwinKernel(process, kernel_load_address); - } - return NULL; -} - -lldb::addr_t -DynamicLoaderDarwinKernel::SearchForDarwinKernel(Process *process) { - addr_t kernel_load_address = process->GetImageInfoAddress(); - if (kernel_load_address == LLDB_INVALID_ADDRESS) { - kernel_load_address = SearchForKernelAtSameLoadAddr(process); - if (kernel_load_address == LLDB_INVALID_ADDRESS) { - kernel_load_address = SearchForKernelWithDebugHints(process); - if (kernel_load_address == LLDB_INVALID_ADDRESS) { - kernel_load_address = SearchForKernelNearPC(process); - if (kernel_load_address == LLDB_INVALID_ADDRESS) { - kernel_load_address = SearchForKernelViaExhaustiveSearch(process); - } - } - } - } - return kernel_load_address; -} - -//---------------------------------------------------------------------- -// Check if the kernel binary is loaded in memory without a slide. First verify -// that the ExecutableModule is a kernel before we proceed. Returns the address -// of the kernel if one was found, else LLDB_INVALID_ADDRESS. -//---------------------------------------------------------------------- -lldb::addr_t -DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) { - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module == NULL) - return LLDB_INVALID_ADDRESS; - - ObjectFile *exe_objfile = exe_module->GetObjectFile(); - if (exe_objfile == NULL) - return LLDB_INVALID_ADDRESS; - - if (exe_objfile->GetType() != ObjectFile::eTypeExecutable || - exe_objfile->GetStrata() != ObjectFile::eStrataKernel) - return LLDB_INVALID_ADDRESS; - - if (!exe_objfile->GetBaseAddress().IsValid()) - return LLDB_INVALID_ADDRESS; - - if (CheckForKernelImageAtAddress( - exe_objfile->GetBaseAddress().GetFileAddress(), process) == - exe_module->GetUUID()) - return exe_objfile->GetBaseAddress().GetFileAddress(); - - return LLDB_INVALID_ADDRESS; -} - -//---------------------------------------------------------------------- -// If the debug flag is included in the boot-args nvram setting, the kernel's -// load address will be noted in the lowglo page at a fixed address Returns the -// address of the kernel if one was found, else LLDB_INVALID_ADDRESS. -//---------------------------------------------------------------------- -lldb::addr_t -DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) { - if (GetGlobalProperties()->GetScanType() == eKASLRScanNone) - return LLDB_INVALID_ADDRESS; - - Status read_err; - addr_t kernel_addresses_64[] = { - 0xfffffff000004010ULL, // newest arm64 devices - 0xffffff8000004010ULL, // 2014-2015-ish arm64 devices - 0xffffff8000002010ULL, // oldest arm64 devices - LLDB_INVALID_ADDRESS}; - addr_t kernel_addresses_32[] = {0xffff0110, // 2016 and earlier armv7 devices - 0xffff1010, - LLDB_INVALID_ADDRESS}; - - uint8_t uval[8]; - if (process->GetAddressByteSize() == 8) { - for (size_t i = 0; kernel_addresses_64[i] != LLDB_INVALID_ADDRESS; i++) { - if (process->ReadMemoryFromInferior (kernel_addresses_64[i], uval, 8, read_err) == 8) - { - DataExtractor data (&uval, 8, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; - uint64_t addr = data.GetU64 (&offset); - if (CheckForKernelImageAtAddress(addr, process).IsValid()) { - return addr; - } - } - } - } - - if (process->GetAddressByteSize() == 4) { - for (size_t i = 0; kernel_addresses_32[i] != LLDB_INVALID_ADDRESS; i++) { - if (process->ReadMemoryFromInferior (kernel_addresses_32[i], uval, 4, read_err) == 4) - { - DataExtractor data (&uval, 4, process->GetByteOrder(), process->GetAddressByteSize()); - offset_t offset = 0; - uint32_t addr = data.GetU32 (&offset); - if (CheckForKernelImageAtAddress(addr, process).IsValid()) { - return addr; - } - } - } - } - - return LLDB_INVALID_ADDRESS; -} - -//---------------------------------------------------------------------- -// If the kernel is currently executing when lldb attaches, and we don't have a -// better way of finding the kernel's load address, try searching backwards -// from the current pc value looking for the kernel's Mach header in memory. -// Returns the address of the kernel if one was found, else -// LLDB_INVALID_ADDRESS. -//---------------------------------------------------------------------- -lldb::addr_t -DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) { - if (GetGlobalProperties()->GetScanType() == eKASLRScanNone || - GetGlobalProperties()->GetScanType() == eKASLRScanLowgloAddresses) { - return LLDB_INVALID_ADDRESS; - } - - ThreadSP thread = process->GetThreadList().GetSelectedThread(); - if (thread.get() == NULL) - return LLDB_INVALID_ADDRESS; - addr_t pc = thread->GetRegisterContext()->GetPC(LLDB_INVALID_ADDRESS); - - // The kernel is always loaded in high memory, if the top bit is zero, - // this isn't a kernel. - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) { - if ((pc & (1ULL << 63)) == 0) { - return LLDB_INVALID_ADDRESS; - } - } else { - if ((pc & (1ULL << 31)) == 0) { - return LLDB_INVALID_ADDRESS; - } - } - - if (pc == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - // The kernel will load at at one megabyte boundary (0x100000), or at that - // boundary plus an offset of one page (0x1000) or two, or four (0x4000), - // depending on the device. - - // Round the current pc down to the nearest one megabyte boundary - the place - // where we will start searching. - addr_t addr = pc & ~0xfffff; - - // Search backwards 32 megabytes, looking for the start of the kernel at each - // one-megabyte boundary. - for (int i = 0; i < 32; i++, addr -= 0x100000) { - // x86_64 kernels are at offset 0 - if (CheckForKernelImageAtAddress(addr, process).IsValid()) - return addr; - // 32-bit arm kernels are at offset 0x1000 (one 4k page) - if (CheckForKernelImageAtAddress(addr + 0x1000, process).IsValid()) - return addr + 0x1000; - // 64-bit arm kernels are at offset 0x4000 (one 16k page) - if (CheckForKernelImageAtAddress(addr + 0x4000, process).IsValid()) - return addr + 0x4000; - } - - return LLDB_INVALID_ADDRESS; -} - -//---------------------------------------------------------------------- -// Scan through the valid address range for a kernel binary. This is uselessly -// slow in 64-bit environments so we don't even try it. This scan is not -// enabled by default even for 32-bit targets. Returns the address of the -// kernel if one was found, else LLDB_INVALID_ADDRESS. -//---------------------------------------------------------------------- -lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch( - Process *process) { - if (GetGlobalProperties()->GetScanType() != eKASLRScanExhaustiveScan) { - return LLDB_INVALID_ADDRESS; - } - - addr_t kernel_range_low, kernel_range_high; - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) { - kernel_range_low = 1ULL << 63; - kernel_range_high = UINT64_MAX; - } else { - kernel_range_low = 1ULL << 31; - kernel_range_high = UINT32_MAX; - } - - // Stepping through memory at one-megabyte resolution looking for a kernel - // rarely works (fast enough) with a 64-bit address space -- for now, let's - // not even bother. We may be attaching to something which *isn't* a kernel - // and we don't want to spin for minutes on-end looking for a kernel. - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) - return LLDB_INVALID_ADDRESS; - - addr_t addr = kernel_range_low; - - while (addr >= kernel_range_low && addr < kernel_range_high) { - // x86_64 kernels are at offset 0 - if (CheckForKernelImageAtAddress(addr, process).IsValid()) - return addr; - // 32-bit arm kernels are at offset 0x1000 (one 4k page) - if (CheckForKernelImageAtAddress(addr + 0x1000, process).IsValid()) - return addr + 0x1000; - // 64-bit arm kernels are at offset 0x4000 (one 16k page) - if (CheckForKernelImageAtAddress(addr + 0x4000, process).IsValid()) - return addr + 0x4000; - addr += 0x100000; - } - return LLDB_INVALID_ADDRESS; -} - -//---------------------------------------------------------------------- -// Read the mach_header struct out of memory and return it. -// Returns true if the mach_header was successfully read, -// Returns false if there was a problem reading the header, or it was not -// a Mach-O header. -//---------------------------------------------------------------------- - -bool -DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::MachO::mach_header &header) { - Status read_error; - - // Read the mach header and see whether it looks like a kernel - if (process->DoReadMemory (addr, &header, sizeof(header), read_error) != - sizeof(header)) - return false; - - const uint32_t magicks[] = { llvm::MachO::MH_MAGIC_64, llvm::MachO::MH_MAGIC, llvm::MachO::MH_CIGAM, llvm::MachO::MH_CIGAM_64}; - - bool found_matching_pattern = false; - for (size_t i = 0; i < llvm::array_lengthof (magicks); i++) - if (::memcmp (&header.magic, &magicks[i], sizeof (uint32_t)) == 0) - found_matching_pattern = true; - - if (!found_matching_pattern) - return false; - - if (header.magic == llvm::MachO::MH_CIGAM || - header.magic == llvm::MachO::MH_CIGAM_64) { - header.magic = llvm::ByteSwap_32(header.magic); - header.cputype = llvm::ByteSwap_32(header.cputype); - header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); - header.filetype = llvm::ByteSwap_32(header.filetype); - header.ncmds = llvm::ByteSwap_32(header.ncmds); - header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); - header.flags = llvm::ByteSwap_32(header.flags); - } - - return true; -} - -//---------------------------------------------------------------------- -// Given an address in memory, look to see if there is a kernel image at that -// address. -// Returns a UUID; if a kernel was not found at that address, UUID.IsValid() -// will be false. -//---------------------------------------------------------------------- -lldb_private::UUID -DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr, - Process *process) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (addr == LLDB_INVALID_ADDRESS) - return UUID(); - - if (log) - log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: " - "looking for kernel binary at 0x%" PRIx64, - addr); - - llvm::MachO::mach_header header; - - if (!ReadMachHeader(addr, process, header)) - return UUID(); - - // First try a quick test -- read the first 4 bytes and see if there is a - // valid Mach-O magic field there - // (the first field of the mach_header/mach_header_64 struct). - // A kernel is an executable which does not have the dynamic link object flag - // set. - if (header.filetype == llvm::MachO::MH_EXECUTE && - (header.flags & llvm::MachO::MH_DYLDLINK) == 0) { - // Create a full module to get the UUID - ModuleSP memory_module_sp = - process->ReadModuleFromMemory(FileSpec("temp_mach_kernel"), addr); - if (!memory_module_sp.get()) - return UUID(); - - ObjectFile *exe_objfile = memory_module_sp->GetObjectFile(); - if (exe_objfile == NULL) { - if (log) - log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress " - "found a binary at 0x%" PRIx64 - " but could not create an object file from memory", - addr); - return UUID(); - } - - if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && - exe_objfile->GetStrata() == ObjectFile::eStrataKernel) { - ArchSpec kernel_arch(eArchTypeMachO, header.cputype, header.cpusubtype); - if (!process->GetTarget().GetArchitecture().IsCompatibleMatch( - kernel_arch)) { - process->GetTarget().SetArchitecture(kernel_arch); - } - if (log) { - std::string uuid_str; - if (memory_module_sp->GetUUID().IsValid()) { - uuid_str = "with UUID "; - uuid_str += memory_module_sp->GetUUID().GetAsString(); - } else { - uuid_str = "and no LC_UUID found in load commands "; - } - log->Printf( - "DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: " - "kernel binary image found at 0x%" PRIx64 " with arch '%s' %s", - addr, kernel_arch.GetTriple().str().c_str(), uuid_str.c_str()); - } - return memory_module_sp->GetUUID(); - } - } - - return UUID(); -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel(Process *process, - lldb::addr_t kernel_addr) - : DynamicLoader(process), m_kernel_load_address(kernel_addr), m_kernel(), - m_kext_summary_header_ptr_addr(), m_kext_summary_header_addr(), - m_kext_summary_header(), m_known_kexts(), m_mutex(), - m_break_id(LLDB_INVALID_BREAK_ID) { - Status error; - PlatformSP platform_sp( - Platform::Create(PlatformDarwinKernel::GetPluginNameStatic(), error)); - // Only select the darwin-kernel Platform if we've been asked to load kexts. - // It can take some time to scan over all of the kext info.plists and that - // shouldn't be done if kext loading is explicitly disabled. - if (platform_sp.get() && GetGlobalProperties()->GetLoadKexts()) { - process->GetTarget().SetPlatform(platform_sp); - } -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -DynamicLoaderDarwinKernel::~DynamicLoaderDarwinKernel() { Clear(true); } - -void DynamicLoaderDarwinKernel::UpdateIfNeeded() { - LoadKernelModuleIfNeeded(); - SetNotificationBreakpointIfNeeded(); -} -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void DynamicLoaderDarwinKernel::DidAttach() { - PrivateInitialize(m_process); - UpdateIfNeeded(); -} - -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void DynamicLoaderDarwinKernel::DidLaunch() { - PrivateInitialize(m_process); - UpdateIfNeeded(); -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void DynamicLoaderDarwinKernel::Clear(bool clear_process) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->ClearBreakpointSiteByID(m_break_id); - - if (clear_process) - m_process = NULL; - m_kernel.Clear(); - m_known_kexts.clear(); - m_kext_summary_header_ptr_addr.Clear(); - m_kext_summary_header_addr.Clear(); - m_break_id = LLDB_INVALID_BREAK_ID; -} - -bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageAtFileAddress( - Process *process) { - if (IsLoaded()) - return true; - - if (m_module_sp) { - bool changed = false; - if (m_module_sp->SetLoadAddress(process->GetTarget(), 0, true, changed)) - m_load_process_stop_id = process->GetStopID(); - } - return false; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetModule(ModuleSP module_sp) { - m_module_sp = module_sp; - if (module_sp.get() && module_sp->GetObjectFile()) { - if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeExecutable && - module_sp->GetObjectFile()->GetStrata() == ObjectFile::eStrataKernel) { - m_kernel_image = true; - } else { - m_kernel_image = false; - } - } -} - -ModuleSP DynamicLoaderDarwinKernel::KextImageInfo::GetModule() { - return m_module_sp; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetLoadAddress( - addr_t load_addr) { - m_load_address = load_addr; -} - -addr_t DynamicLoaderDarwinKernel::KextImageInfo::GetLoadAddress() const { - return m_load_address; -} - -uint64_t DynamicLoaderDarwinKernel::KextImageInfo::GetSize() const { - return m_size; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetSize(uint64_t size) { - m_size = size; -} - -uint32_t DynamicLoaderDarwinKernel::KextImageInfo::GetProcessStopId() const { - return m_load_process_stop_id; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetProcessStopId( - uint32_t stop_id) { - m_load_process_stop_id = stop_id; -} - -bool DynamicLoaderDarwinKernel::KextImageInfo:: -operator==(const KextImageInfo &rhs) { - if (m_uuid.IsValid() || rhs.GetUUID().IsValid()) { - return m_uuid == rhs.GetUUID(); - } - - return m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress(); -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetName(const char *name) { - m_name = name; -} - -std::string DynamicLoaderDarwinKernel::KextImageInfo::GetName() const { - return m_name; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetUUID(const UUID &uuid) { - m_uuid = uuid; -} - -UUID DynamicLoaderDarwinKernel::KextImageInfo::GetUUID() const { - return m_uuid; -} - -// Given the m_load_address from the kext summaries, and a UUID, try to create -// an in-memory Module at that address. Require that the MemoryModule have a -// matching UUID and detect if this MemoryModule is a kernel or a kext. -// -// Returns true if m_memory_module_sp is now set to a valid Module. - -bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule( - Process *process) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (m_memory_module_sp.get() != NULL) - return true; - if (m_load_address == LLDB_INVALID_ADDRESS) - return false; - - FileSpec file_spec(m_name.c_str()); - - llvm::MachO::mach_header mh; - size_t size_to_read = 512; - if (ReadMachHeader(m_load_address, process, mh)) { - if (mh.magic == llvm::MachO::MH_CIGAM || mh.magic == llvm::MachO::MH_MAGIC) - size_to_read = sizeof(llvm::MachO::mach_header) + mh.sizeofcmds; - if (mh.magic == llvm::MachO::MH_CIGAM_64 || - mh.magic == llvm::MachO::MH_MAGIC_64) - size_to_read = sizeof(llvm::MachO::mach_header_64) + mh.sizeofcmds; - } - - ModuleSP memory_module_sp = - process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read); - - if (memory_module_sp.get() == NULL) - return false; - - bool is_kernel = false; - if (memory_module_sp->GetObjectFile()) { - if (memory_module_sp->GetObjectFile()->GetType() == - ObjectFile::eTypeExecutable && - memory_module_sp->GetObjectFile()->GetStrata() == - ObjectFile::eStrataKernel) { - is_kernel = true; - } else if (memory_module_sp->GetObjectFile()->GetType() == - ObjectFile::eTypeSharedLibrary) { - is_kernel = false; - } - } - - // If this is a kext, and the kernel specified what UUID we should find at - // this load address, require that the memory module have a matching UUID or - // something has gone wrong and we should discard it. - if (m_uuid.IsValid()) { - if (m_uuid != memory_module_sp->GetUUID()) { - if (log) { - log->Printf("KextImageInfo::ReadMemoryModule the kernel said to find " - "uuid %s at 0x%" PRIx64 - " but instead we found uuid %s, throwing it away", - m_uuid.GetAsString().c_str(), m_load_address, - memory_module_sp->GetUUID().GetAsString().c_str()); - } - return false; - } - } - - // If the in-memory Module has a UUID, let's use that. - if (!m_uuid.IsValid() && memory_module_sp->GetUUID().IsValid()) { - m_uuid = memory_module_sp->GetUUID(); - } - - m_memory_module_sp = memory_module_sp; - m_kernel_image = is_kernel; - if (is_kernel) { - if (log) { - // This is unusual and probably not intended - log->Printf("KextImageInfo::ReadMemoryModule read the kernel binary out " - "of memory"); - } - if (memory_module_sp->GetArchitecture().IsValid()) { - process->GetTarget().SetArchitecture(memory_module_sp->GetArchitecture()); - } - if (m_uuid.IsValid()) { - ModuleSP exe_module_sp = process->GetTarget().GetExecutableModule(); - if (exe_module_sp.get() && exe_module_sp->GetUUID().IsValid()) { - if (m_uuid != exe_module_sp->GetUUID()) { - // The user specified a kernel binary that has a different UUID than - // the kernel actually running in memory. This never ends well; - // clear the user specified kernel binary from the Target. - - m_module_sp.reset(); - - ModuleList user_specified_kernel_list; - user_specified_kernel_list.Append(exe_module_sp); - process->GetTarget().GetImages().Remove(user_specified_kernel_list); - } - } - } - } - - return true; -} - -bool DynamicLoaderDarwinKernel::KextImageInfo::IsKernel() const { - return m_kernel_image; -} - -void DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel(bool is_kernel) { - m_kernel_image = is_kernel; -} - -bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule( - Process *process) { - if (IsLoaded()) - return true; - - Target &target = process->GetTarget(); - - // If we don't have / can't create a memory module for this kext, don't try - // to load it - we won't have the correct segment load addresses. - if (!ReadMemoryModule(process)) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("Unable to read '%s' from memory at address 0x%" PRIx64 - " to get the segment load addresses.", - m_name.c_str(), m_load_address); - return false; - } - - bool uuid_is_valid = m_uuid.IsValid(); - - if (IsKernel() && uuid_is_valid && m_memory_module_sp.get()) { - Stream *s = target.GetDebugger().GetOutputFile().get(); - if (s) { - s->Printf("Kernel UUID: %s\n", - m_memory_module_sp->GetUUID().GetAsString().c_str()); - s->Printf("Load Address: 0x%" PRIx64 "\n", m_load_address); - } - } - - if (!m_module_sp) { - // See if the kext has already been loaded into the target, probably by the - // user doing target modules add. - const ModuleList &target_images = target.GetImages(); - m_module_sp = target_images.FindModule(m_uuid); - - // Search for the kext on the local filesystem via the UUID - if (!m_module_sp && uuid_is_valid) { - ModuleSpec module_spec; - module_spec.GetUUID() = m_uuid; - module_spec.GetArchitecture() = target.GetArchitecture(); - - // For the kernel, we really do need an on-disk file copy of the binary - // to do anything useful. This will force a clal to - if (IsKernel()) { - if (Symbols::DownloadObjectAndSymbolFile(module_spec, true)) { - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { - m_module_sp.reset(new Module(module_spec.GetFileSpec(), - target.GetArchitecture())); - if (m_module_sp.get() && - m_module_sp->MatchesModuleSpec(module_spec)) { - ModuleList loaded_module_list; - loaded_module_list.Append(m_module_sp); - target.ModulesDidLoad(loaded_module_list); - } - } - } - } - - // If the current platform is PlatformDarwinKernel, create a ModuleSpec - // with the filename set to be the bundle ID for this kext, e.g. - // "com.apple.filesystems.msdosfs", and ask the platform to find it. - PlatformSP platform_sp(target.GetPlatform()); - if (!m_module_sp && platform_sp) { - ConstString platform_name(platform_sp->GetPluginName()); - static ConstString g_platform_name( - PlatformDarwinKernel::GetPluginNameStatic()); - if (platform_name == g_platform_name) { - ModuleSpec kext_bundle_module_spec(module_spec); - FileSpec kext_filespec(m_name.c_str()); - kext_bundle_module_spec.GetFileSpec() = kext_filespec; - platform_sp->GetSharedModule( - kext_bundle_module_spec, process, m_module_sp, - &target.GetExecutableSearchPaths(), NULL, NULL); - } - } - - // Ask the Target to find this file on the local system, if possible. - // This will search in the list of currently-loaded files, look in the - // standard search paths on the system, and on a Mac it will try calling - // the DebugSymbols framework with the UUID to find the binary via its - // search methods. - if (!m_module_sp) { - m_module_sp = target.GetSharedModule(module_spec); - } - - if (IsKernel() && !m_module_sp) { - Stream *s = target.GetDebugger().GetOutputFile().get(); - if (s) { - s->Printf("WARNING: Unable to locate kernel binary on the debugger " - "system.\n"); - } - } - } - - // If we managed to find a module, append it to the target's list of - // images. If we also have a memory module, require that they have matching - // UUIDs - if (m_module_sp) { - bool uuid_match_ok = true; - if (m_memory_module_sp) { - if (m_module_sp->GetUUID() != m_memory_module_sp->GetUUID()) { - uuid_match_ok = false; - } - } - if (uuid_match_ok) { - target.GetImages().AppendIfNeeded(m_module_sp); - if (IsKernel() && - target.GetExecutableModulePointer() != m_module_sp.get()) { - target.SetExecutableModule(m_module_sp, eLoadDependentsNo); - } - } - } - } - - if (!m_module_sp && !IsKernel() && m_uuid.IsValid() && !m_name.empty()) { - Stream *s = target.GetDebugger().GetOutputFile().get(); - if (s) { - s->Printf("warning: Can't find binary/dSYM for %s (%s)\n", m_name.c_str(), - m_uuid.GetAsString().c_str()); - } - } - - static ConstString g_section_name_LINKEDIT("__LINKEDIT"); - - if (m_memory_module_sp && m_module_sp) { - if (m_module_sp->GetUUID() == m_memory_module_sp->GetUUID()) { - ObjectFile *ondisk_object_file = m_module_sp->GetObjectFile(); - ObjectFile *memory_object_file = m_memory_module_sp->GetObjectFile(); - - if (memory_object_file && ondisk_object_file) { - // The memory_module for kexts may have an invalid __LINKEDIT seg; skip - // it. - const bool ignore_linkedit = !IsKernel(); - - SectionList *ondisk_section_list = ondisk_object_file->GetSectionList(); - SectionList *memory_section_list = memory_object_file->GetSectionList(); - if (memory_section_list && ondisk_section_list) { - const uint32_t num_ondisk_sections = ondisk_section_list->GetSize(); - // There may be CTF sections in the memory image so we can't always - // just compare the number of sections (which are actually segments - // in mach-o parlance) - uint32_t sect_idx = 0; - - // Use the memory_module's addresses for each section to set the file - // module's load address as appropriate. We don't want to use a - // single slide value for the entire kext - different segments may be - // slid different amounts by the kext loader. - - uint32_t num_sections_loaded = 0; - for (sect_idx = 0; sect_idx < num_ondisk_sections; ++sect_idx) { - SectionSP ondisk_section_sp( - ondisk_section_list->GetSectionAtIndex(sect_idx)); - if (ondisk_section_sp) { - // Don't ever load __LINKEDIT as it may or may not be actually - // mapped into memory and there is no current way to tell. - // I filed rdar://problem/12851706 to track being able to tell - // if the __LINKEDIT is actually mapped, but until then, we need - // to not load the __LINKEDIT - if (ignore_linkedit && - ondisk_section_sp->GetName() == g_section_name_LINKEDIT) - continue; - - const Section *memory_section = - memory_section_list - ->FindSectionByName(ondisk_section_sp->GetName()) - .get(); - if (memory_section) { - target.SetSectionLoadAddress(ondisk_section_sp, - memory_section->GetFileAddress()); - ++num_sections_loaded; - } - } - } - if (num_sections_loaded > 0) - m_load_process_stop_id = process->GetStopID(); - else - m_module_sp.reset(); // No sections were loaded - } else - m_module_sp.reset(); // One or both section lists - } else - m_module_sp.reset(); // One or both object files missing - } else - m_module_sp.reset(); // UUID mismatch - } - - bool is_loaded = IsLoaded(); - - if (is_loaded && m_module_sp && IsKernel()) { - Stream *s = target.GetDebugger().GetOutputFile().get(); - if (s) { - ObjectFile *kernel_object_file = m_module_sp->GetObjectFile(); - if (kernel_object_file) { - addr_t file_address = - kernel_object_file->GetBaseAddress().GetFileAddress(); - if (m_load_address != LLDB_INVALID_ADDRESS && - file_address != LLDB_INVALID_ADDRESS) { - s->Printf("Kernel slid 0x%" PRIx64 " in memory.\n", - m_load_address - file_address); - } - } - { - s->Printf("Loaded kernel file %s\n", - m_module_sp->GetFileSpec().GetPath().c_str()); - } - s->Flush(); - } - } - return is_loaded; -} - -uint32_t DynamicLoaderDarwinKernel::KextImageInfo::GetAddressByteSize() { - if (m_memory_module_sp) - return m_memory_module_sp->GetArchitecture().GetAddressByteSize(); - if (m_module_sp) - return m_module_sp->GetArchitecture().GetAddressByteSize(); - return 0; -} - -lldb::ByteOrder DynamicLoaderDarwinKernel::KextImageInfo::GetByteOrder() { - if (m_memory_module_sp) - return m_memory_module_sp->GetArchitecture().GetByteOrder(); - if (m_module_sp) - return m_module_sp->GetArchitecture().GetByteOrder(); - return endian::InlHostByteOrder(); -} - -lldb_private::ArchSpec -DynamicLoaderDarwinKernel::KextImageInfo::GetArchitecture() const { - if (m_memory_module_sp) - return m_memory_module_sp->GetArchitecture(); - if (m_module_sp) - return m_module_sp->GetArchitecture(); - return lldb_private::ArchSpec(); -} - -//---------------------------------------------------------------------- -// Load the kernel module and initialize the "m_kernel" member. Return true -// _only_ if the kernel is loaded the first time through (subsequent calls to -// this function should return false after the kernel has been already loaded). -//---------------------------------------------------------------------- -void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() { - if (!m_kext_summary_header_ptr_addr.IsValid()) { - m_kernel.Clear(); - m_kernel.SetModule(m_process->GetTarget().GetExecutableModule()); - m_kernel.SetIsKernel(true); - - ConstString kernel_name("mach_kernel"); - if (m_kernel.GetModule().get() && m_kernel.GetModule()->GetObjectFile() && - !m_kernel.GetModule() - ->GetObjectFile() - ->GetFileSpec() - .GetFilename() - .IsEmpty()) { - kernel_name = - m_kernel.GetModule()->GetObjectFile()->GetFileSpec().GetFilename(); - } - m_kernel.SetName(kernel_name.AsCString()); - - if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS) { - m_kernel.SetLoadAddress(m_kernel_load_address); - if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS && - m_kernel.GetModule()) { - // We didn't get a hint from the process, so we will try the kernel at - // the address that it exists at in the file if we have one - ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile(); - if (kernel_object_file) { - addr_t load_address = - kernel_object_file->GetBaseAddress().GetLoadAddress( - &m_process->GetTarget()); - addr_t file_address = - kernel_object_file->GetBaseAddress().GetFileAddress(); - if (load_address != LLDB_INVALID_ADDRESS && load_address != 0) { - m_kernel.SetLoadAddress(load_address); - if (load_address != file_address) { - // Don't accidentally relocate the kernel to the File address -- - // the Load address has already been set to its actual in-memory - // address. Mark it as IsLoaded. - m_kernel.SetProcessStopId(m_process->GetStopID()); - } - } else { - m_kernel.SetLoadAddress(file_address); - } - } - } - } - - if (m_kernel.GetLoadAddress() != LLDB_INVALID_ADDRESS) { - if (!m_kernel.LoadImageUsingMemoryModule(m_process)) { - m_kernel.LoadImageAtFileAddress(m_process); - } - } - - // The operating system plugin gets loaded and initialized in - // LoadImageUsingMemoryModule when we discover the kernel dSYM. For a core - // file in particular, that's the wrong place to do this, since we haven't - // fixed up the section addresses yet. So let's redo it here. - LoadOperatingSystemPlugin(false); - - if (m_kernel.IsLoaded() && m_kernel.GetModule()) { - static ConstString kext_summary_symbol("gLoadedKextSummaries"); - const Symbol *symbol = - m_kernel.GetModule()->FindFirstSymbolWithNameAndType( - kext_summary_symbol, eSymbolTypeData); - if (symbol) { - m_kext_summary_header_ptr_addr = symbol->GetAddress(); - // Update all image infos - ReadAllKextSummaries(); - } - } else { - m_kernel.Clear(); - } - } -} - -//---------------------------------------------------------------------- -// Static callback function that gets called when our DYLD notification -// breakpoint gets hit. We update all of our image infos and then let our super -// class DynamicLoader class decide if we should stop or not (based on global -// preference). -//---------------------------------------------------------------------- -bool DynamicLoaderDarwinKernel::BreakpointHitCallback( - void *baton, StoppointCallbackContext *context, user_id_t break_id, - user_id_t break_loc_id) { - return static_cast<DynamicLoaderDarwinKernel *>(baton)->BreakpointHit( - context, break_id, break_loc_id); -} - -bool DynamicLoaderDarwinKernel::BreakpointHit(StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("DynamicLoaderDarwinKernel::BreakpointHit (...)\n"); - - ReadAllKextSummaries(); - - if (log) - PutToLog(log); - - return GetStopWhenImagesChange(); -} - -bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader() { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // the all image infos is already valid for this process stop ID - - if (m_kext_summary_header_ptr_addr.IsValid()) { - const uint32_t addr_size = m_kernel.GetAddressByteSize(); - const ByteOrder byte_order = m_kernel.GetByteOrder(); - Status error; - // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure which - // is currently 4 uint32_t and a pointer. - uint8_t buf[24]; - DataExtractor data(buf, sizeof(buf), byte_order, addr_size); - const size_t count = 4 * sizeof(uint32_t) + addr_size; - const bool prefer_file_cache = false; - if (m_process->GetTarget().ReadPointerFromMemory( - m_kext_summary_header_ptr_addr, prefer_file_cache, error, - m_kext_summary_header_addr)) { - // We got a valid address for our kext summary header and make sure it - // isn't NULL - if (m_kext_summary_header_addr.IsValid() && - m_kext_summary_header_addr.GetFileAddress() != 0) { - const size_t bytes_read = m_process->GetTarget().ReadMemory( - m_kext_summary_header_addr, prefer_file_cache, buf, count, error); - if (bytes_read == count) { - lldb::offset_t offset = 0; - m_kext_summary_header.version = data.GetU32(&offset); - if (m_kext_summary_header.version > 128) { - Stream *s = - m_process->GetTarget().GetDebugger().GetOutputFile().get(); - s->Printf("WARNING: Unable to read kext summary header, got " - "improbable version number %u\n", - m_kext_summary_header.version); - // If we get an improbably large version number, we're probably - // getting bad memory. - m_kext_summary_header_addr.Clear(); - return false; - } - if (m_kext_summary_header.version >= 2) { - m_kext_summary_header.entry_size = data.GetU32(&offset); - if (m_kext_summary_header.entry_size > 4096) { - // If we get an improbably large entry_size, we're probably - // getting bad memory. - Stream *s = - m_process->GetTarget().GetDebugger().GetOutputFile().get(); - s->Printf("WARNING: Unable to read kext summary header, got " - "improbable entry_size %u\n", - m_kext_summary_header.entry_size); - m_kext_summary_header_addr.Clear(); - return false; - } - } else { - // Versions less than 2 didn't have an entry size, it was hard - // coded - m_kext_summary_header.entry_size = - KERNEL_MODULE_ENTRY_SIZE_VERSION_1; - } - m_kext_summary_header.entry_count = data.GetU32(&offset); - if (m_kext_summary_header.entry_count > 10000) { - // If we get an improbably large number of kexts, we're probably - // getting bad memory. - Stream *s = - m_process->GetTarget().GetDebugger().GetOutputFile().get(); - s->Printf("WARNING: Unable to read kext summary header, got " - "improbable number of kexts %u\n", - m_kext_summary_header.entry_count); - m_kext_summary_header_addr.Clear(); - return false; - } - return true; - } - } - } - } - m_kext_summary_header_addr.Clear(); - return false; -} - -// We've either (a) just attached to a new kernel, or (b) the kexts-changed -// breakpoint was hit and we need to figure out what kexts have been added or -// removed. Read the kext summaries from the inferior kernel memory, compare -// them against the m_known_kexts vector and update the m_known_kexts vector as -// needed to keep in sync with the inferior. - -bool DynamicLoaderDarwinKernel::ParseKextSummaries( - const Address &kext_summary_addr, uint32_t count) { - KextImageInfo::collection kext_summaries; - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("Kexts-changed breakpoint hit, there are %d kexts currently.\n", - count); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (!ReadKextSummaries(kext_summary_addr, count, kext_summaries)) - return false; - - // read the plugin.dynamic-loader.darwin-kernel.load-kexts setting -- if the - // user requested no kext loading, don't print any messages about kexts & - // don't try to read them. - const bool load_kexts = GetGlobalProperties()->GetLoadKexts(); - - // By default, all kexts we've loaded in the past are marked as "remove" and - // all of the kexts we just found out about from ReadKextSummaries are marked - // as "add". - std::vector<bool> to_be_removed(m_known_kexts.size(), true); - std::vector<bool> to_be_added(count, true); - - int number_of_new_kexts_being_added = 0; - int number_of_old_kexts_being_removed = m_known_kexts.size(); - - const uint32_t new_kexts_size = kext_summaries.size(); - const uint32_t old_kexts_size = m_known_kexts.size(); - - // The m_known_kexts vector may have entries that have been Cleared, or are a - // kernel. - for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++) { - bool ignore = false; - KextImageInfo &image_info = m_known_kexts[old_kext]; - if (image_info.IsKernel()) { - ignore = true; - } else if (image_info.GetLoadAddress() == LLDB_INVALID_ADDRESS && - !image_info.GetModule()) { - ignore = true; - } - - if (ignore) { - number_of_old_kexts_being_removed--; - to_be_removed[old_kext] = false; - } - } - - // Scan over the list of kexts we just read from the kernel, note those that - // need to be added and those already loaded. - for (uint32_t new_kext = 0; new_kext < new_kexts_size; new_kext++) { - bool add_this_one = true; - for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++) { - if (m_known_kexts[old_kext] == kext_summaries[new_kext]) { - // We already have this kext, don't re-load it. - to_be_added[new_kext] = false; - // This kext is still present, do not remove it. - to_be_removed[old_kext] = false; - - number_of_old_kexts_being_removed--; - add_this_one = false; - break; - } - } - // If this "kext" entry is actually an alias for the kernel -- the kext was - // compiled into the kernel or something -- then we don't want to load the - // kernel's text section at a different address. Ignore this kext entry. - if (kext_summaries[new_kext].GetUUID().IsValid() - && m_kernel.GetUUID().IsValid() - && kext_summaries[new_kext].GetUUID() == m_kernel.GetUUID()) { - to_be_added[new_kext] = false; - break; - } - if (add_this_one) { - number_of_new_kexts_being_added++; - } - } - - if (number_of_new_kexts_being_added == 0 && - number_of_old_kexts_being_removed == 0) - return true; - - Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get(); - if (s && load_kexts) { - if (number_of_new_kexts_being_added > 0 && - number_of_old_kexts_being_removed > 0) { - s->Printf("Loading %d kext modules and unloading %d kext modules ", - number_of_new_kexts_being_added, - number_of_old_kexts_being_removed); - } else if (number_of_new_kexts_being_added > 0) { - s->Printf("Loading %d kext modules ", number_of_new_kexts_being_added); - } else if (number_of_old_kexts_being_removed > 0) { - s->Printf("Unloading %d kext modules ", - number_of_old_kexts_being_removed); - } - } - - if (log) { - if (load_kexts) { - log->Printf("DynamicLoaderDarwinKernel::ParseKextSummaries: %d kexts " - "added, %d kexts removed", - number_of_new_kexts_being_added, - number_of_old_kexts_being_removed); - } else { - log->Printf( - "DynamicLoaderDarwinKernel::ParseKextSummaries kext loading is " - "disabled, else would have %d kexts added, %d kexts removed", - number_of_new_kexts_being_added, number_of_old_kexts_being_removed); - } - } - - if (number_of_new_kexts_being_added > 0) { - ModuleList loaded_module_list; - - const uint32_t num_of_new_kexts = kext_summaries.size(); - for (uint32_t new_kext = 0; new_kext < num_of_new_kexts; new_kext++) { - if (to_be_added[new_kext]) { - KextImageInfo &image_info = kext_summaries[new_kext]; - if (load_kexts) { - if (!image_info.LoadImageUsingMemoryModule(m_process)) { - image_info.LoadImageAtFileAddress(m_process); - } - } - - m_known_kexts.push_back(image_info); - - if (image_info.GetModule() && - m_process->GetStopID() == image_info.GetProcessStopId()) - loaded_module_list.AppendIfNeeded(image_info.GetModule()); - - if (s && load_kexts) - s->Printf("."); - - if (log) - kext_summaries[new_kext].PutToLog(log); - } - } - m_process->GetTarget().ModulesDidLoad(loaded_module_list); - } - - if (number_of_old_kexts_being_removed > 0) { - ModuleList loaded_module_list; - const uint32_t num_of_old_kexts = m_known_kexts.size(); - for (uint32_t old_kext = 0; old_kext < num_of_old_kexts; old_kext++) { - ModuleList unloaded_module_list; - if (to_be_removed[old_kext]) { - KextImageInfo &image_info = m_known_kexts[old_kext]; - // You can't unload the kernel. - if (!image_info.IsKernel()) { - if (image_info.GetModule()) { - unloaded_module_list.AppendIfNeeded(image_info.GetModule()); - } - if (s) - s->Printf("."); - image_info.Clear(); - // should pull it out of the KextImageInfos vector but that would - // mutate the list and invalidate the to_be_removed bool vector; - // leaving it in place once Cleared() is relatively harmless. - } - } - m_process->GetTarget().ModulesDidUnload(unloaded_module_list, false); - } - } - - if (s && load_kexts) { - s->Printf(" done.\n"); - s->Flush(); - } - - return true; -} - -uint32_t DynamicLoaderDarwinKernel::ReadKextSummaries( - const Address &kext_summary_addr, uint32_t image_infos_count, - KextImageInfo::collection &image_infos) { - const ByteOrder endian = m_kernel.GetByteOrder(); - const uint32_t addr_size = m_kernel.GetAddressByteSize(); - - image_infos.resize(image_infos_count); - const size_t count = image_infos.size() * m_kext_summary_header.entry_size; - DataBufferHeap data(count, 0); - Status error; - - const bool prefer_file_cache = false; - const size_t bytes_read = m_process->GetTarget().ReadMemory( - kext_summary_addr, prefer_file_cache, data.GetBytes(), data.GetByteSize(), - error); - if (bytes_read == count) { - - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), endian, - addr_size); - uint32_t i = 0; - for (uint32_t kext_summary_offset = 0; - i < image_infos.size() && - extractor.ValidOffsetForDataOfSize(kext_summary_offset, - m_kext_summary_header.entry_size); - ++i, kext_summary_offset += m_kext_summary_header.entry_size) { - lldb::offset_t offset = kext_summary_offset; - const void *name_data = - extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME); - if (name_data == NULL) - break; - image_infos[i].SetName((const char *)name_data); - UUID uuid = UUID::fromOptionalData(extractor.GetData(&offset, 16), 16); - image_infos[i].SetUUID(uuid); - image_infos[i].SetLoadAddress(extractor.GetU64(&offset)); - image_infos[i].SetSize(extractor.GetU64(&offset)); - } - if (i < image_infos.size()) - image_infos.resize(i); - } else { - image_infos.clear(); - } - return image_infos.size(); -} - -bool DynamicLoaderDarwinKernel::ReadAllKextSummaries() { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (ReadKextSummaryHeader()) { - if (m_kext_summary_header.entry_count > 0 && - m_kext_summary_header_addr.IsValid()) { - Address summary_addr(m_kext_summary_header_addr); - summary_addr.Slide(m_kext_summary_header.GetSize()); - if (!ParseKextSummaries(summary_addr, - m_kext_summary_header.entry_count)) { - m_known_kexts.clear(); - } - return true; - } - } - return false; -} - -//---------------------------------------------------------------------- -// Dump an image info structure to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const { - if (m_load_address == LLDB_INVALID_ADDRESS) { - LLDB_LOG(log, "uuid={0} name=\"{1}\" (UNLOADED)", m_uuid.GetAsString(), - m_name); - } else { - LLDB_LOG(log, "addr={0:x+16} size={1:x+16} uuid={2} name=\"{3}\"", - m_load_address, m_size, m_uuid.GetAsString(), m_name); - } -} - -//---------------------------------------------------------------------- -// Dump the _dyld_all_image_infos members and all current image infos that we -// have parsed to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderDarwinKernel::PutToLog(Log *log) const { - if (log == NULL) - return; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - log->Printf("gLoadedKextSummaries = 0x%16.16" PRIx64 - " { version=%u, entry_size=%u, entry_count=%u }", - m_kext_summary_header_addr.GetFileAddress(), - m_kext_summary_header.version, m_kext_summary_header.entry_size, - m_kext_summary_header.entry_count); - - size_t i; - const size_t count = m_known_kexts.size(); - if (count > 0) { - log->PutCString("Loaded:"); - for (i = 0; i < count; i++) - m_known_kexts[i].PutToLog(log); - } -} - -void DynamicLoaderDarwinKernel::PrivateInitialize(Process *process) { - DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", - __FUNCTION__, StateAsCString(m_process->GetState())); - Clear(true); - m_process = process; -} - -void DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded() { - if (m_break_id == LLDB_INVALID_BREAK_ID && m_kernel.GetModule()) { - DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s() process state = %s\n", - __FUNCTION__, StateAsCString(m_process->GetState())); - - const bool internal_bp = true; - const bool hardware = false; - const LazyBool skip_prologue = eLazyBoolNo; - FileSpecList module_spec_list; - module_spec_list.Append(m_kernel.GetModule()->GetFileSpec()); - Breakpoint *bp = - m_process->GetTarget() - .CreateBreakpoint(&module_spec_list, NULL, - "OSKextLoadedKextSummariesUpdated", - eFunctionNameTypeFull, eLanguageTypeUnknown, 0, - skip_prologue, internal_bp, hardware) - .get(); - - bp->SetCallback(DynamicLoaderDarwinKernel::BreakpointHitCallback, this, - true); - m_break_id = bp->GetID(); - } -} - -//---------------------------------------------------------------------- -// Member function that gets called when the process state changes. -//---------------------------------------------------------------------- -void DynamicLoaderDarwinKernel::PrivateProcessStateChanged(Process *process, - StateType state) { - DEBUG_PRINTF("DynamicLoaderDarwinKernel::%s(%s)\n", __FUNCTION__, - StateAsCString(state)); - switch (state) { - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - case eStateDetached: - Clear(false); - break; - - case eStateStopped: - UpdateIfNeeded(); - break; - - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - break; - } -} - -ThreadPlanSP -DynamicLoaderDarwinKernel::GetStepThroughTrampolinePlan(Thread &thread, - bool stop_others) { - ThreadPlanSP thread_plan_sp; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Could not find symbol for step through."); - return thread_plan_sp; -} - -Status DynamicLoaderDarwinKernel::CanLoadImage() { - Status error; - error.SetErrorString( - "always unsafe to load or unload shared libraries in the darwin kernel"); - return error; -} - -void DynamicLoaderDarwinKernel::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - DebuggerInitialize); -} - -void DynamicLoaderDarwinKernel::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -void DynamicLoaderDarwinKernel::DebuggerInitialize( - lldb_private::Debugger &debugger) { - if (!PluginManager::GetSettingForDynamicLoaderPlugin( - debugger, DynamicLoaderDarwinKernelProperties::GetSettingName())) { - const bool is_global_setting = true; - PluginManager::CreateSettingForDynamicLoaderPlugin( - debugger, GetGlobalProperties()->GetValueProperties(), - ConstString("Properties for the DynamicLoaderDarwinKernel plug-in."), - is_global_setting); - } -} - -lldb_private::ConstString DynamicLoaderDarwinKernel::GetPluginNameStatic() { - static ConstString g_name("darwin-kernel"); - return g_name; -} - -const char *DynamicLoaderDarwinKernel::GetPluginDescriptionStatic() { - return "Dynamic loader plug-in that watches for shared library loads/unloads " - "in the MacOSX kernel."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString DynamicLoaderDarwinKernel::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t DynamicLoaderDarwinKernel::GetPluginVersion() { return 1; } - -lldb::ByteOrder -DynamicLoaderDarwinKernel::GetByteOrderFromMagic(uint32_t magic) { - switch (magic) { - case llvm::MachO::MH_MAGIC: - case llvm::MachO::MH_MAGIC_64: - return endian::InlHostByteOrder(); - - case llvm::MachO::MH_CIGAM: - case llvm::MachO::MH_CIGAM_64: - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - return lldb::eByteOrderLittle; - else - return lldb::eByteOrderBig; - - default: - break; - } - return lldb::eByteOrderInvalid; -} diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h deleted file mode 100644 index 7aacebd9b50fb..0000000000000 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h +++ /dev/null @@ -1,307 +0,0 @@ -//===-- DynamicLoaderDarwinKernel.h -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_DynamicLoaderDarwinKernel_h_ -#define liblldb_DynamicLoaderDarwinKernel_h_ - -#include <mutex> -#include <string> -#include <vector> - - -#include "lldb/Host/SafeMachO.h" - -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/UUID.h" - -class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader { -public: - DynamicLoaderDarwinKernel(lldb_private::Process *process, - lldb::addr_t kernel_addr); - - ~DynamicLoaderDarwinKernel() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - static void DebuggerInitialize(lldb_private::Debugger &debugger); - - static lldb::addr_t SearchForDarwinKernel(lldb_private::Process *process); - - //------------------------------------------------------------------ - /// Called after attaching a process. - /// - /// Allow DynamicLoader plug-ins to execute some code after - /// attaching to a process. - //------------------------------------------------------------------ - void DidAttach() override; - - void DidLaunch() override; - - lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others) override; - - lldb_private::Status CanLoadImage() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - void PrivateInitialize(lldb_private::Process *process); - - void PrivateProcessStateChanged(lldb_private::Process *process, - lldb::StateType state); - - void UpdateIfNeeded(); - - void LoadKernelModuleIfNeeded(); - - void Clear(bool clear_process); - - void PutToLog(lldb_private::Log *log) const; - - static bool - BreakpointHitCallback(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - bool BreakpointHit(lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - uint32_t GetAddrByteSize() { return m_kernel.GetAddressByteSize(); } - - static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); - - enum { - KERNEL_MODULE_MAX_NAME = 64u, - // Versions less than 2 didn't have an entry size, - // they had a 64 bit name, 16 byte UUID, 8 byte addr, - // 8 byte size, 8 byte version, 4 byte load tag, and - // 4 byte flags - KERNEL_MODULE_ENTRY_SIZE_VERSION_1 = 64u + 16u + 8u + 8u + 8u + 4u + 4u - }; - - // class KextImageInfo represents a single kext or kernel binary image. - // The class was designed to hold the information from the - // OSKextLoadedKextSummary - // structure (in libkern/libkern/OSKextLibPrivate.h from xnu). The kernel - // maintains - // a list of loded kexts in memory (the OSKextLoadedKextSummaryHeader - // structure, - // which points to an array of OSKextLoadedKextSummary's). - // - // A KextImageInfos may have - - // - // 1. The load address, name, UUID, and size of a kext/kernel binary in memory - // (read straight out of the kernel's list-of-kexts loaded) - // 2. A ModuleSP based on a MemoryModule read out of the kernel's memory - // (very unlikely to have any symbolic information) - // 3. A ModuleSP for an on-disk copy of the kext binary, possibly with debug - // info - // or a dSYM - // - // For performance reasons, the developer may prefer that lldb not load the - // kexts out - // of memory at the start of a kernel session. But we should build up / - // maintain a - // list of kexts that the kernel has told us about so we can relocate a kext - // module - // later if the user explicitly adds it to the target. - - class KextImageInfo { - public: - KextImageInfo() - : m_name(), m_module_sp(), m_memory_module_sp(), - m_load_process_stop_id(UINT32_MAX), m_uuid(), - m_load_address(LLDB_INVALID_ADDRESS), m_size(0), - m_kernel_image(false) {} - - void Clear() { - m_load_address = LLDB_INVALID_ADDRESS; - m_size = 0; - m_name.clear(); - m_uuid.Clear(); - m_module_sp.reset(); - m_memory_module_sp.reset(); - m_load_process_stop_id = UINT32_MAX; - } - - bool LoadImageAtFileAddress(lldb_private::Process *process); - - bool LoadImageUsingMemoryModule(lldb_private::Process *process); - - bool IsLoaded() { return m_load_process_stop_id != UINT32_MAX; } - - void SetLoadAddress( - lldb::addr_t load_addr); // Address of the Mach-O header for this binary - - lldb::addr_t - GetLoadAddress() const; // Address of the Mach-O header for this binary - - lldb_private::UUID GetUUID() const; - - void SetUUID(const lldb_private::UUID &uuid); - - void SetName(const char *); - - std::string GetName() const; - - void SetModule(lldb::ModuleSP module); - - lldb::ModuleSP GetModule(); - - // try to fill in m_memory_module_sp from memory based on the m_load_address - bool ReadMemoryModule(lldb_private::Process *process); - - bool IsKernel() - const; // true if this is the mach_kernel; false if this is a kext - - void SetIsKernel(bool is_kernel); - - uint64_t GetSize() const; - - void SetSize(uint64_t size); - - uint32_t - GetProcessStopId() const; // the stop-id when this binary was first noticed - - void SetProcessStopId(uint32_t stop_id); - - bool operator==(const KextImageInfo &rhs); - - uint32_t GetAddressByteSize(); // as determined by Mach-O header - - lldb::ByteOrder GetByteOrder(); // as determined by Mach-O header - - lldb_private::ArchSpec - GetArchitecture() const; // as determined by Mach-O header - - void PutToLog(lldb_private::Log *log) const; - - typedef std::vector<KextImageInfo> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - - private: - std::string m_name; - lldb::ModuleSP m_module_sp; - lldb::ModuleSP m_memory_module_sp; - uint32_t m_load_process_stop_id; // the stop-id when this module was added - // to the Target - lldb_private::UUID - m_uuid; // UUID for this dylib if it has one, else all zeros - lldb::addr_t m_load_address; - uint64_t m_size; - bool m_kernel_image; // true if this is the kernel, false if this is a kext - }; - - struct OSKextLoadedKextSummaryHeader { - uint32_t version; - uint32_t entry_size; - uint32_t entry_count; - lldb::addr_t image_infos_addr; - - OSKextLoadedKextSummaryHeader() - : version(0), entry_size(0), entry_count(0), - image_infos_addr(LLDB_INVALID_ADDRESS) {} - - uint32_t GetSize() { - switch (version) { - case 0: - return 0; // Can't know the size without a valid version - case 1: - return 8; // Version 1 only had a version + entry_count - default: - break; - } - // Version 2 and above has version, entry_size, entry_count, and reserved - return 16; - } - - void Clear() { - version = 0; - entry_size = 0; - entry_count = 0; - image_infos_addr = LLDB_INVALID_ADDRESS; - } - - bool IsValid() const { return version >= 1 || version <= 2; } - }; - - void RegisterNotificationCallbacks(); - - void UnregisterNotificationCallbacks(); - - void SetNotificationBreakpointIfNeeded(); - - bool ReadAllKextSummaries(); - - bool ReadKextSummaryHeader(); - - bool ParseKextSummaries(const lldb_private::Address &kext_summary_addr, - uint32_t count); - - void - UpdateImageInfosHeaderAndLoadCommands(KextImageInfo::collection &image_infos, - uint32_t infos_count, - bool update_executable); - - uint32_t ReadKextSummaries(const lldb_private::Address &kext_summary_addr, - uint32_t image_infos_count, - KextImageInfo::collection &image_infos); - - static lldb::addr_t - SearchForKernelAtSameLoadAddr(lldb_private::Process *process); - - static lldb::addr_t - SearchForKernelWithDebugHints(lldb_private::Process *process); - - static lldb::addr_t SearchForKernelNearPC(lldb_private::Process *process); - - static lldb::addr_t - SearchForKernelViaExhaustiveSearch(lldb_private::Process *process); - - static bool - ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh); - - static lldb_private::UUID - CheckForKernelImageAtAddress(lldb::addr_t addr, - lldb_private::Process *process); - - lldb::addr_t m_kernel_load_address; - KextImageInfo m_kernel; // Info about the current kernel image being used - - lldb_private::Address m_kext_summary_header_ptr_addr; - lldb_private::Address m_kext_summary_header_addr; - OSKextLoadedKextSummaryHeader m_kext_summary_header; - KextImageInfo::collection m_known_kexts; - mutable std::recursive_mutex m_mutex; - lldb::user_id_t m_break_id; - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderDarwinKernel); -}; - -#endif // liblldb_DynamicLoaderDarwinKernel_h_ diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/CMakeLists.txt b/source/Plugins/DynamicLoader/Hexagon-DYLD/CMakeLists.txt deleted file mode 100644 index c590457d0a54d..0000000000000 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderHexagonDYLD PLUGIN - HexagonDYLDRendezvous.cpp - DynamicLoaderHexagonDYLD.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbSymbol - lldbTarget - ) diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt b/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt deleted file mode 100644 index 515c82dcaca97..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD PLUGIN - DynamicLoaderMacOSXDYLD.cpp - DynamicLoaderMacOS.cpp - DynamicLoaderDarwin.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbHost - lldbSymbol - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp deleted file mode 100644 index 944be9633e00e..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -//===-- DynamicLoaderDarwin.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DynamicLoaderDarwin.h" - -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/ABI.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanCallFunction.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" - -//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#include <stdio.h> -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif - -#ifndef __APPLE__ -#include "Utility/UuidCompatibility.h" -#else -#include <uuid/uuid.h> -#endif - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -DynamicLoaderDarwin::DynamicLoaderDarwin(Process *process) - : DynamicLoader(process), m_dyld_module_wp(), m_libpthread_module_wp(), - m_pthread_getspecific_addr(), m_tid_to_tls_map(), m_dyld_image_infos(), - m_dyld_image_infos_stop_id(UINT32_MAX), m_dyld(), m_mutex() {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -DynamicLoaderDarwin::~DynamicLoaderDarwin() {} - -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void DynamicLoaderDarwin::DidAttach() { - PrivateInitialize(m_process); - DoInitialImageFetch(); - SetNotificationBreakpoint(); -} - -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void DynamicLoaderDarwin::DidLaunch() { - PrivateInitialize(m_process); - DoInitialImageFetch(); - SetNotificationBreakpoint(); -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void DynamicLoaderDarwin::Clear(bool clear_process) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (clear_process) - m_process = NULL; - m_dyld_image_infos.clear(); - m_dyld_image_infos_stop_id = UINT32_MAX; - m_dyld.Clear(false); -} - -ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo( - ImageInfo &image_info, bool can_create, bool *did_create_ptr) { - if (did_create_ptr) - *did_create_ptr = false; - - Target &target = m_process->GetTarget(); - const ModuleList &target_images = target.GetImages(); - ModuleSpec module_spec(image_info.file_spec); - module_spec.GetUUID() = image_info.uuid; - ModuleSP module_sp(target_images.FindFirstModule(module_spec)); - - if (module_sp && !module_spec.GetUUID().IsValid() && - !module_sp->GetUUID().IsValid()) { - // No UUID, we must rely upon the cached module modification time and the - // modification time of the file on disk - if (module_sp->GetModificationTime() != - FileSystem::Instance().GetModificationTime(module_sp->GetFileSpec())) - module_sp.reset(); - } - - if (!module_sp) { - if (can_create) { - module_sp = target.GetSharedModule(module_spec); - if (!module_sp || module_sp->GetObjectFile() == NULL) - module_sp = m_process->ReadModuleFromMemory(image_info.file_spec, - image_info.address); - - if (did_create_ptr) - *did_create_ptr = (bool)module_sp; - } - } - return module_sp; -} - -void DynamicLoaderDarwin::UnloadImages( - const std::vector<lldb::addr_t> &solib_addresses) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (m_process->GetStopID() == m_dyld_image_infos_stop_id) - return; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - Target &target = m_process->GetTarget(); - if (log) - log->Printf("Removing %" PRId64 " modules.", - (uint64_t)solib_addresses.size()); - - ModuleList unloaded_module_list; - - for (addr_t solib_addr : solib_addresses) { - Address header; - if (header.SetLoadAddress(solib_addr, &target)) { - if (header.GetOffset() == 0) { - ModuleSP module_to_remove(header.GetModule()); - if (module_to_remove.get()) { - if (log) - log->Printf("Removing module at address 0x%" PRIx64, solib_addr); - // remove the sections from the Target - UnloadSections(module_to_remove); - // add this to the list of modules to remove - unloaded_module_list.AppendIfNeeded(module_to_remove); - // remove the entry from the m_dyld_image_infos - ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); - for (pos = m_dyld_image_infos.begin(); pos != end; pos++) { - if (solib_addr == (*pos).address) { - m_dyld_image_infos.erase(pos); - break; - } - } - } - } - } - } - - if (unloaded_module_list.GetSize() > 0) { - if (log) { - log->PutCString("Unloaded:"); - unloaded_module_list.LogUUIDAndPaths( - log, "DynamicLoaderDarwin::UnloadModules"); - } - m_process->GetTarget().GetImages().Remove(unloaded_module_list); - m_dyld_image_infos_stop_id = m_process->GetStopID(); - } -} - -void DynamicLoaderDarwin::UnloadAllImages() { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ModuleList unloaded_modules_list; - - Target &target = m_process->GetTarget(); - const ModuleList &target_modules = target.GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - - size_t num_modules = target_modules.GetSize(); - ModuleSP dyld_sp(GetDYLDModule()); - - for (size_t i = 0; i < num_modules; i++) { - ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i); - - // Don't remove dyld - else we'll lose our breakpoint notifying us about - // libraries being re-loaded... - if (module_sp.get() != nullptr && module_sp.get() != dyld_sp.get()) { - UnloadSections(module_sp); - unloaded_modules_list.Append(module_sp); - } - } - - if (unloaded_modules_list.GetSize() != 0) { - if (log) { - log->PutCString("Unloaded:"); - unloaded_modules_list.LogUUIDAndPaths( - log, "DynamicLoaderDarwin::UnloadAllImages"); - } - target.GetImages().Remove(unloaded_modules_list); - m_dyld_image_infos.clear(); - m_dyld_image_infos_stop_id = m_process->GetStopID(); - } -} - -//---------------------------------------------------------------------- -// Update the load addresses for all segments in MODULE using the updated INFO -// that is passed in. -//---------------------------------------------------------------------- -bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module, - ImageInfo &info) { - bool changed = false; - if (module) { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) { - SectionList *section_list = image_object_file->GetSectionList(); - if (section_list) { - std::vector<uint32_t> inaccessible_segment_indexes; - // We now know the slide amount, so go through all sections and update - // the load addresses with the correct values. - const size_t num_segments = info.segments.size(); - for (size_t i = 0; i < num_segments; ++i) { - // Only load a segment if it has protections. Things like __PAGEZERO - // don't have any protections, and they shouldn't be slid - SectionSP section_sp( - section_list->FindSectionByName(info.segments[i].name)); - - if (info.segments[i].maxprot == 0) { - inaccessible_segment_indexes.push_back(i); - } else { - const addr_t new_section_load_addr = - info.segments[i].vmaddr + info.slide; - static ConstString g_section_name_LINKEDIT("__LINKEDIT"); - - if (section_sp) { - // __LINKEDIT sections from files in the shared cache can overlap - // so check to see what the segment name is and pass "false" so - // we don't warn of overlapping "Section" objects, and "true" for - // all other sections. - const bool warn_multiple = - section_sp->GetName() != g_section_name_LINKEDIT; - - changed = m_process->GetTarget().SetSectionLoadAddress( - section_sp, new_section_load_addr, warn_multiple); - } else { - Host::SystemLog( - Host::eSystemLogWarning, - "warning: unable to find and load segment named '%s' at " - "0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString("<invalid>"), - (uint64_t)new_section_load_addr, - image_object_file->GetFileSpec().GetPath().c_str()); - } - } - } - - // If the loaded the file (it changed) and we have segments that are - // not readable or writeable, add them to the invalid memory region - // cache for the process. This will typically only be the __PAGEZERO - // segment in the main executable. We might be able to apply this more - // generally to more sections that have no protections in the future, - // but for now we are going to just do __PAGEZERO. - if (changed && !inaccessible_segment_indexes.empty()) { - for (uint32_t i = 0; i < inaccessible_segment_indexes.size(); ++i) { - const uint32_t seg_idx = inaccessible_segment_indexes[i]; - SectionSP section_sp( - section_list->FindSectionByName(info.segments[seg_idx].name)); - - if (section_sp) { - static ConstString g_pagezero_section_name("__PAGEZERO"); - if (g_pagezero_section_name == section_sp->GetName()) { - // __PAGEZERO never slides... - const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr; - const lldb::addr_t vmsize = info.segments[seg_idx].vmsize; - Process::LoadRange pagezero_range(vmaddr, vmsize); - m_process->AddInvalidMemoryRegion(pagezero_range); - } - } - } - } - } - } - } - // We might have an in memory image that was loaded as soon as it was created - if (info.load_stop_id == m_process->GetStopID()) - changed = true; - else if (changed) { - // Update the stop ID when this library was updated - info.load_stop_id = m_process->GetStopID(); - } - return changed; -} - -//---------------------------------------------------------------------- -// Unload the segments in MODULE using the INFO that is passed in. -//---------------------------------------------------------------------- -bool DynamicLoaderDarwin::UnloadModuleSections(Module *module, - ImageInfo &info) { - bool changed = false; - if (module) { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) { - SectionList *section_list = image_object_file->GetSectionList(); - if (section_list) { - const size_t num_segments = info.segments.size(); - for (size_t i = 0; i < num_segments; ++i) { - SectionSP section_sp( - section_list->FindSectionByName(info.segments[i].name)); - if (section_sp) { - const addr_t old_section_load_addr = - info.segments[i].vmaddr + info.slide; - if (m_process->GetTarget().SetSectionUnloaded( - section_sp, old_section_load_addr)) - changed = true; - } else { - Host::SystemLog(Host::eSystemLogWarning, - "warning: unable to find and unload segment named " - "'%s' in '%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString("<invalid>"), - image_object_file->GetFileSpec().GetPath().c_str()); - } - } - } - } - } - return changed; -} - -// Given a JSON dictionary (from debugserver, most likely) of binary images -// loaded in the inferior process, add the images to the ImageInfo collection. - -bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo( - StructuredData::ObjectSP image_details, - ImageInfo::collection &image_infos) { - StructuredData::ObjectSP images_sp = - image_details->GetAsDictionary()->GetValueForKey("images"); - if (images_sp.get() == nullptr) - return false; - - image_infos.resize(images_sp->GetAsArray()->GetSize()); - - for (size_t i = 0; i < image_infos.size(); i++) { - StructuredData::ObjectSP image_sp = - images_sp->GetAsArray()->GetItemAtIndex(i); - if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr) - return false; - StructuredData::Dictionary *image = image_sp->GetAsDictionary(); - // clang-format off - if (!image->HasKey("load_address") || - !image->HasKey("pathname") || - !image->HasKey("mod_date") || - !image->HasKey("mach_header") || - image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr || - !image->HasKey("segments") || - image->GetValueForKey("segments")->GetAsArray() == nullptr || - !image->HasKey("uuid")) { - return false; - } - // clang-format on - image_infos[i].address = - image->GetValueForKey("load_address")->GetAsInteger()->GetValue(); - image_infos[i].mod_date = - image->GetValueForKey("mod_date")->GetAsInteger()->GetValue(); - image_infos[i].file_spec.SetFile( - image->GetValueForKey("pathname")->GetAsString()->GetValue(), - FileSpec::Style::native); - - StructuredData::Dictionary *mh = - image->GetValueForKey("mach_header")->GetAsDictionary(); - image_infos[i].header.magic = - mh->GetValueForKey("magic")->GetAsInteger()->GetValue(); - image_infos[i].header.cputype = - mh->GetValueForKey("cputype")->GetAsInteger()->GetValue(); - image_infos[i].header.cpusubtype = - mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue(); - image_infos[i].header.filetype = - mh->GetValueForKey("filetype")->GetAsInteger()->GetValue(); - - if (image->HasKey("min_version_os_name")) { - std::string os_name = image->GetValueForKey("min_version_os_name") - ->GetAsString() - ->GetValue(); - if (os_name == "macosx") - image_infos[i].os_type = llvm::Triple::MacOSX; - else if (os_name == "ios" || os_name == "iphoneos") - image_infos[i].os_type = llvm::Triple::IOS; - else if (os_name == "tvos") - image_infos[i].os_type = llvm::Triple::TvOS; - else if (os_name == "watchos") - image_infos[i].os_type = llvm::Triple::WatchOS; - // NEED_BRIDGEOS_TRIPLE else if (os_name == "bridgeos") - // NEED_BRIDGEOS_TRIPLE image_infos[i].os_type = llvm::Triple::BridgeOS; - } - if (image->HasKey("min_version_os_sdk")) { - image_infos[i].min_version_os_sdk = - image->GetValueForKey("min_version_os_sdk") - ->GetAsString() - ->GetValue(); - } - - // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't - // currently send them in the reply. - - if (mh->HasKey("flags")) - image_infos[i].header.flags = - mh->GetValueForKey("flags")->GetAsInteger()->GetValue(); - else - image_infos[i].header.flags = 0; - - if (mh->HasKey("ncmds")) - image_infos[i].header.ncmds = - mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue(); - else - image_infos[i].header.ncmds = 0; - - if (mh->HasKey("sizeofcmds")) - image_infos[i].header.sizeofcmds = - mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue(); - else - image_infos[i].header.sizeofcmds = 0; - - StructuredData::Array *segments = - image->GetValueForKey("segments")->GetAsArray(); - uint32_t segcount = segments->GetSize(); - for (size_t j = 0; j < segcount; j++) { - Segment segment; - StructuredData::Dictionary *seg = - segments->GetItemAtIndex(j)->GetAsDictionary(); - segment.name = - ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue()); - segment.vmaddr = - seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue(); - segment.vmsize = - seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue(); - segment.fileoff = - seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue(); - segment.filesize = - seg->GetValueForKey("filesize")->GetAsInteger()->GetValue(); - segment.maxprot = - seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue(); - - // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't - // currently send them in the reply. - - if (seg->HasKey("initprot")) - segment.initprot = - seg->GetValueForKey("initprot")->GetAsInteger()->GetValue(); - else - segment.initprot = 0; - - if (seg->HasKey("flags")) - segment.flags = - seg->GetValueForKey("flags")->GetAsInteger()->GetValue(); - else - segment.flags = 0; - - if (seg->HasKey("nsects")) - segment.nsects = - seg->GetValueForKey("nsects")->GetAsInteger()->GetValue(); - else - segment.nsects = 0; - - image_infos[i].segments.push_back(segment); - } - - image_infos[i].uuid.SetFromStringRef( - image->GetValueForKey("uuid")->GetAsString()->GetValue()); - - // All sections listed in the dyld image info structure will all either be - // fixed up already, or they will all be off by a single slide amount that - // is determined by finding the first segment that is at file offset zero - // which also has bytes (a file size that is greater than zero) in the - // object file. - - // Determine the slide amount (if any) - const size_t num_sections = image_infos[i].segments.size(); - for (size_t k = 0; k < num_sections; ++k) { - // Iterate through the object file sections to find the first section - // that starts of file offset zero and that has bytes in the file... - if ((image_infos[i].segments[k].fileoff == 0 && - image_infos[i].segments[k].filesize > 0) || - (image_infos[i].segments[k].name == ConstString("__TEXT"))) { - image_infos[i].slide = - image_infos[i].address - image_infos[i].segments[k].vmaddr; - // We have found the slide amount, so we can exit this for loop. - break; - } - } - } - - return true; -} - -void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos( - ImageInfo::collection &image_infos) { - uint32_t exe_idx = UINT32_MAX; - uint32_t dyld_idx = UINT32_MAX; - Target &target = m_process->GetTarget(); - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ConstString g_dyld_sim_filename("dyld_sim"); - - ArchSpec target_arch = target.GetArchitecture(); - const size_t image_infos_size = image_infos.size(); - for (size_t i = 0; i < image_infos_size; i++) { - if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) { - // In a "simulator" process (an x86 process that is - // ios/tvos/watchos/bridgeos) we will have two dyld modules -- - // a "dyld" that we want to keep track of, and a "dyld_sim" which - // we don't need to keep track of here. If the target is an x86 - // system and the OS of the dyld binary is ios/tvos/watchos/bridgeos, - // then we are looking at dyld_sym. - - // debugserver has only recently (late 2016) started sending up the os - // type for each binary it sees -- so if we don't have an os type, use a - // filename check as our next best guess. - if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS) { - if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename) { - dyld_idx = i; - } - } else if (target_arch.GetTriple().getArch() == llvm::Triple::x86 || - target_arch.GetTriple().getArch() == llvm::Triple::x86_64) { - if (image_infos[i].os_type != llvm::Triple::OSType::IOS && - image_infos[i].os_type != llvm::Triple::TvOS && - image_infos[i].os_type != llvm::Triple::WatchOS) { - // NEED_BRIDGEOS_TRIPLE image_infos[i].os_type != llvm::Triple::BridgeOS) { - dyld_idx = i; - } - } - else { - // catch-all for any other environment -- trust that dyld is actually - // dyld - dyld_idx = i; - } - } else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) { - exe_idx = i; - } - } - - if (exe_idx != UINT32_MAX) { - const bool can_create = true; - ModuleSP exe_module_sp( - FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL)); - if (exe_module_sp) { - if (log) - log->Printf("Found executable module: %s", - exe_module_sp->GetFileSpec().GetPath().c_str()); - target.GetImages().AppendIfNeeded(exe_module_sp); - UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]); - if (exe_module_sp.get() != target.GetExecutableModulePointer()) { - target.SetExecutableModule(exe_module_sp, eLoadDependentsNo); - } - } - } - - if (dyld_idx != UINT32_MAX) { - const bool can_create = true; - ModuleSP dyld_sp = - FindTargetModuleForImageInfo(image_infos[dyld_idx], can_create, NULL); - if (dyld_sp.get()) { - if (log) - log->Printf("Found dyld module: %s", - dyld_sp->GetFileSpec().GetPath().c_str()); - target.GetImages().AppendIfNeeded(dyld_sp); - UpdateImageLoadAddress(dyld_sp.get(), image_infos[dyld_idx]); - SetDYLDModule(dyld_sp); - } - } -} - -void DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo( - ImageInfo &image_info) { - if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) { - const bool can_create = true; - ModuleSP dyld_sp = - FindTargetModuleForImageInfo(image_info, can_create, NULL); - if (dyld_sp.get()) { - Target &target = m_process->GetTarget(); - target.GetImages().AppendIfNeeded(dyld_sp); - UpdateImageLoadAddress(dyld_sp.get(), image_info); - SetDYLDModule(dyld_sp); - } - } -} - -void DynamicLoaderDarwin::SetDYLDModule(lldb::ModuleSP &dyld_module_sp) { - m_dyld_module_wp = dyld_module_sp; -} - -ModuleSP DynamicLoaderDarwin::GetDYLDModule() { - ModuleSP dyld_sp(m_dyld_module_wp.lock()); - return dyld_sp; -} - -bool DynamicLoaderDarwin::AddModulesUsingImageInfos( - ImageInfo::collection &image_infos) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - // Now add these images to the main list. - ModuleList loaded_module_list; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - Target &target = m_process->GetTarget(); - ModuleList &target_images = target.GetImages(); - - for (uint32_t idx = 0; idx < image_infos.size(); ++idx) { - if (log) { - log->Printf("Adding new image at address=0x%16.16" PRIx64 ".", - image_infos[idx].address); - image_infos[idx].PutToLog(log); - } - - m_dyld_image_infos.push_back(image_infos[idx]); - - ModuleSP image_module_sp( - FindTargetModuleForImageInfo(image_infos[idx], true, NULL)); - - if (image_module_sp) { - ObjectFile *objfile = image_module_sp->GetObjectFile(); - if (objfile) { - SectionList *sections = objfile->GetSectionList(); - if (sections) { - ConstString commpage_dbstr("__commpage"); - Section *commpage_section = - sections->FindSectionByName(commpage_dbstr).get(); - if (commpage_section) { - ModuleSpec module_spec(objfile->GetFileSpec(), - image_infos[idx].GetArchitecture()); - module_spec.GetObjectName() = commpage_dbstr; - ModuleSP commpage_image_module_sp( - target_images.FindFirstModule(module_spec)); - if (!commpage_image_module_sp) { - module_spec.SetObjectOffset(objfile->GetFileOffset() + - commpage_section->GetFileOffset()); - module_spec.SetObjectSize(objfile->GetByteSize()); - commpage_image_module_sp = target.GetSharedModule(module_spec); - if (!commpage_image_module_sp || - commpage_image_module_sp->GetObjectFile() == NULL) { - commpage_image_module_sp = m_process->ReadModuleFromMemory( - image_infos[idx].file_spec, image_infos[idx].address); - // Always load a memory image right away in the target in case - // we end up trying to read the symbol table from memory... The - // __LINKEDIT will need to be mapped so we can figure out where - // the symbol table bits are... - bool changed = false; - UpdateImageLoadAddress(commpage_image_module_sp.get(), - image_infos[idx]); - target.GetImages().Append(commpage_image_module_sp); - if (changed) { - image_infos[idx].load_stop_id = m_process->GetStopID(); - loaded_module_list.AppendIfNeeded(commpage_image_module_sp); - } - } - } - } - } - } - - // UpdateImageLoadAddress will return true if any segments change load - // address. We need to check this so we don't mention that all loaded - // shared libraries are newly loaded each time we hit out dyld breakpoint - // since dyld will list all shared libraries each time. - if (UpdateImageLoadAddress(image_module_sp.get(), image_infos[idx])) { - target_images.AppendIfNeeded(image_module_sp); - loaded_module_list.AppendIfNeeded(image_module_sp); - } - } - } - - if (loaded_module_list.GetSize() > 0) { - if (log) - loaded_module_list.LogUUIDAndPaths(log, - "DynamicLoaderDarwin::ModulesDidLoad"); - m_process->GetTarget().ModulesDidLoad(loaded_module_list); - } - return true; -} - -//---------------------------------------------------------------------- -// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch -// functions written in hand-written assembly, and also have hand-written -// unwind information in the eh_frame section. Normally we prefer analyzing -// the assembly instructions of a currently executing frame to unwind from that -// frame -- but on hand-written functions this profiling can fail. We should -// use the eh_frame instructions for these functions all the time. -// -// As an aside, it would be better if the eh_frame entries had a flag (or were -// extensible so they could have an Apple-specific flag) which indicates that -// the instructions are asynchronous -- accurate at every instruction, instead -// of our normal default assumption that they are not. -//---------------------------------------------------------------------- - -bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext &sym_ctx) { - ModuleSP module_sp; - if (sym_ctx.symbol) { - module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); - } - if (module_sp.get() == NULL && sym_ctx.function) { - module_sp = - sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); - } - if (module_sp.get() == NULL) - return false; - - ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); - return objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary(module_sp); -} - -//---------------------------------------------------------------------- -// Dump a Segment to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderDarwin::Segment::PutToLog(Log *log, - lldb::addr_t slide) const { - if (log) { - if (slide == 0) - log->Printf("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")", - name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize); - else - log->Printf("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 - ") slide = 0x%" PRIx64, - name.AsCString(""), vmaddr + slide, vmaddr + slide + vmsize, - slide); - } -} - -const DynamicLoaderDarwin::Segment * -DynamicLoaderDarwin::ImageInfo::FindSegment(const ConstString &name) const { - const size_t num_segments = segments.size(); - for (size_t i = 0; i < num_segments; ++i) { - if (segments[i].name == name) - return &segments[i]; - } - return NULL; -} - -//---------------------------------------------------------------------- -// Dump an image info structure to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderDarwin::ImageInfo::PutToLog(Log *log) const { - if (!log) - return; - if (address == LLDB_INVALID_ADDRESS) { - LLDB_LOG(log, "modtime={0:x+8} uuid={1} path='{2}' (UNLOADED)", mod_date, - uuid.GetAsString(), file_spec.GetPath()); - } else { - LLDB_LOG(log, "address={0:x+16} modtime={1:x+8} uuid={2} path='{3}'", - address, mod_date, uuid.GetAsString(), file_spec.GetPath()); - for (uint32_t i = 0; i < segments.size(); ++i) - segments[i].PutToLog(log, slide); - } -} - -void DynamicLoaderDarwin::PrivateInitialize(Process *process) { - DEBUG_PRINTF("DynamicLoaderDarwin::%s() process state = %s\n", __FUNCTION__, - StateAsCString(m_process->GetState())); - Clear(true); - m_process = process; - m_process->GetTarget().ClearAllLoadedSections(); -} - -//---------------------------------------------------------------------- -// Member function that gets called when the process state changes. -//---------------------------------------------------------------------- -void DynamicLoaderDarwin::PrivateProcessStateChanged(Process *process, - StateType state) { - DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__, - StateAsCString(state)); - switch (state) { - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - case eStateDetached: - Clear(false); - break; - - case eStateStopped: - // Keep trying find dyld and set our notification breakpoint each time we - // stop until we succeed - if (!DidSetNotificationBreakpoint() && m_process->IsAlive()) { - if (NeedToDoInitialImageFetch()) - DoInitialImageFetch(); - - SetNotificationBreakpoint(); - } - break; - - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - break; - } -} - -ThreadPlanSP -DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread, - bool stop_others) { - ThreadPlanSP thread_plan_sp; - StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext ¤t_context = - current_frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *current_symbol = current_context.symbol; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - TargetSP target_sp(thread.CalculateTarget()); - - if (current_symbol != NULL) { - std::vector<Address> addresses; - - if (current_symbol->IsTrampoline()) { - const ConstString &trampoline_name = current_symbol->GetMangled().GetName( - current_symbol->GetLanguage(), Mangled::ePreferMangled); - - if (trampoline_name) { - const ModuleList &images = target_sp->GetImages(); - - SymbolContextList code_symbols; - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, - code_symbols); - size_t num_code_symbols = code_symbols.GetSize(); - - if (num_code_symbols > 0) { - for (uint32_t i = 0; i < num_code_symbols; i++) { - SymbolContext context; - AddressRange addr_range; - if (code_symbols.GetContextAtIndex(i, context)) { - context.GetAddressRange(eSymbolContextEverything, 0, false, - addr_range); - addresses.push_back(addr_range.GetBaseAddress()); - if (log) { - addr_t load_addr = - addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); - - log->Printf("Found a trampoline target symbol at 0x%" PRIx64 - ".", - load_addr); - } - } - } - } - - SymbolContextList reexported_symbols; - images.FindSymbolsWithNameAndType( - trampoline_name, eSymbolTypeReExported, reexported_symbols); - size_t num_reexported_symbols = reexported_symbols.GetSize(); - if (num_reexported_symbols > 0) { - for (uint32_t i = 0; i < num_reexported_symbols; i++) { - SymbolContext context; - if (reexported_symbols.GetContextAtIndex(i, context)) { - if (context.symbol) { - Symbol *actual_symbol = - context.symbol->ResolveReExportedSymbol(*target_sp.get()); - if (actual_symbol) { - const Address actual_symbol_addr = - actual_symbol->GetAddress(); - if (actual_symbol_addr.IsValid()) { - addresses.push_back(actual_symbol_addr); - if (log) { - lldb::addr_t load_addr = - actual_symbol_addr.GetLoadAddress(target_sp.get()); - log->Printf( - "Found a re-exported symbol: %s at 0x%" PRIx64 ".", - actual_symbol->GetName().GetCString(), load_addr); - } - } - } - } - } - } - } - - SymbolContextList indirect_symbols; - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, - indirect_symbols); - size_t num_indirect_symbols = indirect_symbols.GetSize(); - if (num_indirect_symbols > 0) { - for (uint32_t i = 0; i < num_indirect_symbols; i++) { - SymbolContext context; - AddressRange addr_range; - if (indirect_symbols.GetContextAtIndex(i, context)) { - context.GetAddressRange(eSymbolContextEverything, 0, false, - addr_range); - addresses.push_back(addr_range.GetBaseAddress()); - if (log) { - addr_t load_addr = - addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); - - log->Printf("Found an indirect target symbol at 0x%" PRIx64 ".", - load_addr); - } - } - } - } - } - } else if (current_symbol->GetType() == eSymbolTypeReExported) { - // I am not sure we could ever end up stopped AT a re-exported symbol. - // But just in case: - - const Symbol *actual_symbol = - current_symbol->ResolveReExportedSymbol(*(target_sp.get())); - if (actual_symbol) { - Address target_addr(actual_symbol->GetAddress()); - if (target_addr.IsValid()) { - if (log) - log->Printf( - "Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 - ".", - current_symbol->GetName().GetCString(), - actual_symbol->GetName().GetCString(), - target_addr.GetLoadAddress(target_sp.get())); - addresses.push_back(target_addr.GetLoadAddress(target_sp.get())); - } - } - } - - if (addresses.size() > 0) { - // First check whether any of the addresses point to Indirect symbols, - // and if they do, resolve them: - std::vector<lldb::addr_t> load_addrs; - for (Address address : addresses) { - Symbol *symbol = address.CalculateSymbolContextSymbol(); - if (symbol && symbol->IsIndirect()) { - Status error; - Address symbol_address = symbol->GetAddress(); - addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction( - &symbol_address, error); - if (error.Success()) { - load_addrs.push_back(resolved_addr); - if (log) - log->Printf("ResolveIndirectFunction found resolved target for " - "%s at 0x%" PRIx64 ".", - symbol->GetName().GetCString(), resolved_addr); - } - } else { - load_addrs.push_back(address.GetLoadAddress(target_sp.get())); - } - } - thread_plan_sp.reset( - new ThreadPlanRunToAddress(thread, load_addrs, stop_others)); - } - } else { - if (log) - log->Printf("Could not find symbol for step through."); - } - - return thread_plan_sp; -} - -size_t DynamicLoaderDarwin::FindEquivalentSymbols( - lldb_private::Symbol *original_symbol, lldb_private::ModuleList &images, - lldb_private::SymbolContextList &equivalent_symbols) { - const ConstString &trampoline_name = original_symbol->GetMangled().GetName( - original_symbol->GetLanguage(), Mangled::ePreferMangled); - if (!trampoline_name) - return 0; - - size_t initial_size = equivalent_symbols.GetSize(); - - static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$"; - std::string equivalent_regex_buf("^"); - equivalent_regex_buf.append(trampoline_name.GetCString()); - equivalent_regex_buf.append(resolver_name_regex); - - RegularExpression equivalent_name_regex(equivalent_regex_buf); - const bool append = true; - images.FindSymbolsMatchingRegExAndType(equivalent_name_regex, eSymbolTypeCode, - equivalent_symbols, append); - - return equivalent_symbols.GetSize() - initial_size; -} - -lldb::ModuleSP DynamicLoaderDarwin::GetPThreadLibraryModule() { - ModuleSP module_sp = m_libpthread_module_wp.lock(); - if (!module_sp) { - SymbolContextList sc_list; - ModuleSpec module_spec; - module_spec.GetFileSpec().GetFilename().SetCString( - "libsystem_pthread.dylib"); - ModuleList module_list; - if (m_process->GetTarget().GetImages().FindModules(module_spec, - module_list)) { - if (module_list.GetSize() == 1) { - module_sp = module_list.GetModuleAtIndex(0); - if (module_sp) - m_libpthread_module_wp = module_sp; - } - } - } - return module_sp; -} - -Address DynamicLoaderDarwin::GetPthreadSetSpecificAddress() { - if (!m_pthread_getspecific_addr.IsValid()) { - ModuleSP module_sp = GetPThreadLibraryModule(); - if (module_sp) { - lldb_private::SymbolContextList sc_list; - module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"), - eSymbolTypeCode, sc_list); - SymbolContext sc; - if (sc_list.GetContextAtIndex(0, sc)) { - if (sc.symbol) - m_pthread_getspecific_addr = sc.symbol->GetAddress(); - } - } - } - return m_pthread_getspecific_addr; -} - -lldb::addr_t -DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, - const lldb::ThreadSP thread_sp, - lldb::addr_t tls_file_addr) { - if (!thread_sp || !module_sp) - return LLDB_INVALID_ADDRESS; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - const uint32_t addr_size = m_process->GetAddressByteSize(); - uint8_t buf[sizeof(lldb::addr_t) * 3]; - - lldb_private::Address tls_addr; - if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) { - Status error; - const size_t tsl_data_size = addr_size * 3; - Target &target = m_process->GetTarget(); - if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) == - tsl_data_size) { - const ByteOrder byte_order = m_process->GetByteOrder(); - DataExtractor data(buf, sizeof(buf), byte_order, addr_size); - lldb::offset_t offset = addr_size; // Skip the first pointer - const lldb::addr_t pthread_key = data.GetAddress(&offset); - const lldb::addr_t tls_offset = data.GetAddress(&offset); - if (pthread_key != 0) { - // First check to see if we have already figured out the location of - // TLS data for the pthread_key on a specific thread yet. If we have we - // can re-use it since its location will not change unless the process - // execs. - const tid_t tid = thread_sp->GetID(); - auto tid_pos = m_tid_to_tls_map.find(tid); - if (tid_pos != m_tid_to_tls_map.end()) { - auto tls_pos = tid_pos->second.find(pthread_key); - if (tls_pos != tid_pos->second.end()) { - return tls_pos->second + tls_offset; - } - } - StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0); - if (frame_sp) { - ClangASTContext *clang_ast_context = - target.GetScratchClangASTContext(); - - if (!clang_ast_context) - return LLDB_INVALID_ADDRESS; - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Address pthread_getspecific_addr = GetPthreadSetSpecificAddress(); - if (pthread_getspecific_addr.IsValid()) { - EvaluateExpressionOptions options; - - lldb::ThreadPlanSP thread_plan_sp(new ThreadPlanCallFunction( - *thread_sp, pthread_getspecific_addr, clang_void_ptr_type, - llvm::ArrayRef<lldb::addr_t>(pthread_key), options)); - - DiagnosticManager execution_errors; - ExecutionContext exe_ctx(thread_sp); - lldb::ExpressionResults results = m_process->RunThreadPlan( - exe_ctx, thread_plan_sp, options, execution_errors); - - if (results == lldb::eExpressionCompleted) { - lldb::ValueObjectSP result_valobj_sp = - thread_plan_sp->GetReturnValueObject(); - if (result_valobj_sp) { - const lldb::addr_t pthread_key_data = - result_valobj_sp->GetValueAsUnsigned(0); - if (pthread_key_data) { - m_tid_to_tls_map[tid].insert( - std::make_pair(pthread_key, pthread_key_data)); - return pthread_key_data + tls_offset; - } - } - } - } - } - } - } - } - return LLDB_INVALID_ADDRESS; -} - -bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - bool use_new_spi_interface = false; - - llvm::VersionTuple version = process->GetHostOSVersion(); - if (!version.empty()) { - const llvm::Triple::OSType os_type = - process->GetTarget().GetArchitecture().GetTriple().getOS(); - - // macOS 10.12 and newer - if (os_type == llvm::Triple::MacOSX && - version >= llvm::VersionTuple(10, 12)) - use_new_spi_interface = true; - - // iOS 10 and newer - if (os_type == llvm::Triple::IOS && version >= llvm::VersionTuple(10)) - use_new_spi_interface = true; - - // tvOS 10 and newer - if (os_type == llvm::Triple::TvOS && version >= llvm::VersionTuple(10)) - use_new_spi_interface = true; - - // watchOS 3 and newer - if (os_type == llvm::Triple::WatchOS && version >= llvm::VersionTuple(3)) - use_new_spi_interface = true; - - // NEED_BRIDGEOS_TRIPLE // Any BridgeOS - // NEED_BRIDGEOS_TRIPLE if (os_type == llvm::Triple::BridgeOS) - // NEED_BRIDGEOS_TRIPLE use_new_spi_interface = true; - } - - if (log) { - if (use_new_spi_interface) - log->Printf( - "DynamicLoaderDarwin::UseDYLDSPI: Use new DynamicLoader plugin"); - else - log->Printf( - "DynamicLoaderDarwin::UseDYLDSPI: Use old DynamicLoader plugin"); - } - return use_new_spi_interface; -} diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h deleted file mode 100644 index 690253ba5ff2c..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h +++ /dev/null @@ -1,241 +0,0 @@ -//===-- DynamicLoaderDarwin.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_DynamicLoaderDarwin_h_ -#define liblldb_DynamicLoaderDarwin_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Host/SafeMachO.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/UUID.h" - -#include "llvm/ADT/Triple.h" - -namespace lldb_private { - -class DynamicLoaderDarwin : public lldb_private::DynamicLoader { -public: - DynamicLoaderDarwin(lldb_private::Process *process); - - virtual ~DynamicLoaderDarwin() override; - - //------------------------------------------------------------------ - /// Called after attaching a process. - /// - /// Allow DynamicLoader plug-ins to execute some code after - /// attaching to a process. - //------------------------------------------------------------------ - void DidAttach() override; - - void DidLaunch() override; - - lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others) override; - - size_t FindEquivalentSymbols( - lldb_private::Symbol *original_symbol, - lldb_private::ModuleList &module_list, - lldb_private::SymbolContextList &equivalent_symbols) override; - - lldb::addr_t GetThreadLocalData(const lldb::ModuleSP module, - const lldb::ThreadSP thread, - lldb::addr_t tls_file_addr) override; - - bool AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; - - virtual void DoInitialImageFetch() = 0; - - virtual bool NeedToDoInitialImageFetch() = 0; - -protected: - void PrivateInitialize(lldb_private::Process *process); - - void PrivateProcessStateChanged(lldb_private::Process *process, - lldb::StateType state); - - void Clear(bool clear_process); - - // Clear method for classes derived from this one - virtual void DoClear() = 0; - - void SetDYLDModule(lldb::ModuleSP &dyld_module_sp); - - lldb::ModuleSP GetDYLDModule(); - - class Segment { - public: - Segment() - : name(), vmaddr(LLDB_INVALID_ADDRESS), vmsize(0), fileoff(0), - filesize(0), maxprot(0), initprot(0), nsects(0), flags(0) {} - - lldb_private::ConstString name; - lldb::addr_t vmaddr; - lldb::addr_t vmsize; - lldb::addr_t fileoff; - lldb::addr_t filesize; - uint32_t maxprot; - uint32_t initprot; - uint32_t nsects; - uint32_t flags; - - bool operator==(const Segment &rhs) const { - return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; - } - - void PutToLog(lldb_private::Log *log, lldb::addr_t slide) const; - }; - - struct ImageInfo { - lldb::addr_t address; // Address of mach header for this dylib - lldb::addr_t slide; // The amount to slide all segments by if there is a - // global slide. - lldb::addr_t mod_date; // Modification date for this dylib - lldb_private::FileSpec file_spec; // Resolved path for this dylib - lldb_private::UUID - uuid; // UUID for this dylib if it has one, else all zeros - llvm::MachO::mach_header header; // The mach header for this image - std::vector<Segment> segments; // All segment vmaddr and vmsize pairs for - // this executable (from memory of inferior) - uint32_t load_stop_id; // The process stop ID that the sections for this - // image were loaded - llvm::Triple::OSType os_type; // LC_VERSION_MIN_... load command os type - std::string min_version_os_sdk; // LC_VERSION_MIN_... sdk value - - ImageInfo() - : address(LLDB_INVALID_ADDRESS), slide(0), mod_date(0), file_spec(), - uuid(), header(), segments(), load_stop_id(0), - os_type(llvm::Triple::OSType::UnknownOS), min_version_os_sdk() {} - - void Clear(bool load_cmd_data_only) { - if (!load_cmd_data_only) { - address = LLDB_INVALID_ADDRESS; - slide = 0; - mod_date = 0; - file_spec.Clear(); - ::memset(&header, 0, sizeof(header)); - } - uuid.Clear(); - segments.clear(); - load_stop_id = 0; - os_type = llvm::Triple::OSType::UnknownOS; - min_version_os_sdk.clear(); - } - - bool operator==(const ImageInfo &rhs) const { - return address == rhs.address && slide == rhs.slide && - mod_date == rhs.mod_date && file_spec == rhs.file_spec && - uuid == rhs.uuid && - memcmp(&header, &rhs.header, sizeof(header)) == 0 && - segments == rhs.segments && os_type == rhs.os_type; - } - - bool UUIDValid() const { return uuid.IsValid(); } - - uint32_t GetAddressByteSize() { - if (header.cputype) { - if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) - return 8; - else - return 4; - } - return 0; - } - - lldb_private::ArchSpec GetArchitecture() const { - return lldb_private::ArchSpec(lldb_private::eArchTypeMachO, - header.cputype, header.cpusubtype); - } - - const Segment *FindSegment(const lldb_private::ConstString &name) const; - - void PutToLog(lldb_private::Log *log) const; - - typedef std::vector<ImageInfo> collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - }; - - bool UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo &info); - - bool UnloadModuleSections(lldb_private::Module *module, ImageInfo &info); - - lldb::ModuleSP FindTargetModuleForImageInfo(ImageInfo &image_info, - bool can_create, - bool *did_create_ptr); - - void UnloadImages(const std::vector<lldb::addr_t> &solib_addresses); - - void UnloadAllImages(); - - virtual bool SetNotificationBreakpoint() = 0; - - virtual void ClearNotificationBreakpoint() = 0; - - virtual bool DidSetNotificationBreakpoint() = 0; - - typedef std::map<uint64_t, lldb::addr_t> PthreadKeyToTLSMap; - typedef std::map<lldb::user_id_t, PthreadKeyToTLSMap> ThreadIDToTLSMap; - - std::recursive_mutex &GetMutex() const { return m_mutex; } - - lldb::ModuleSP GetPThreadLibraryModule(); - - lldb_private::Address GetPthreadSetSpecificAddress(); - - bool JSONImageInformationIntoImageInfo( - lldb_private::StructuredData::ObjectSP image_details, - ImageInfo::collection &image_infos); - - // If image_infos contains / may contain dyld or executable image, call this - // method - // to keep our internal record keeping of the special binaries up-to-date. - void - UpdateSpecialBinariesFromNewImageInfos(ImageInfo::collection &image_infos); - - // if image_info is a dyld binary, call this method - void UpdateDYLDImageInfoFromNewImageInfo(ImageInfo &image_info); - - // If image_infos contains / may contain executable image, call this method - // to keep our internal record keeping of the special dyld binary up-to-date. - void AddExecutableModuleIfInImageInfos(ImageInfo::collection &image_infos); - - bool AddModulesUsingImageInfos(ImageInfo::collection &image_infos); - - // Whether we should use the new dyld SPI to get shared library information, - // or read - // it directly out of the dyld_all_image_infos. Whether we use the (newer) - // DynamicLoaderMacOS - // plugin or the (older) DynamicLoaderMacOSX plugin. - static bool UseDYLDSPI(lldb_private::Process *process); - - lldb::ModuleWP m_dyld_module_wp; // the dyld whose file type (mac, ios, etc) - // matches the process - lldb::ModuleWP m_libpthread_module_wp; - lldb_private::Address m_pthread_getspecific_addr; - ThreadIDToTLSMap m_tid_to_tls_map; - ImageInfo::collection - m_dyld_image_infos; // Current shared libraries information - uint32_t m_dyld_image_infos_stop_id; // The process stop ID that - // "m_dyld_image_infos" is valid for - ImageInfo m_dyld; - mutable std::recursive_mutex m_mutex; - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderDarwin); -}; - -} // namespace lldb_private - -#endif // liblldb_DynamicLoaderDarwin_h_ diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp deleted file mode 100644 index 1ff0ec2c79377..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp +++ /dev/null @@ -1,548 +0,0 @@ -//===-- DynamicLoaderMacOS.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Target/ABI.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" - -#include "DynamicLoaderDarwin.h" -#include "DynamicLoaderMacOS.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process, - bool force) { - bool create = force; - if (!create) { - create = true; - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - create = (object_file->GetStrata() == ObjectFile::eStrataUser); - } - } - - if (create) { - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - create = triple_ref.getVendor() == llvm::Triple::Apple; - break; - default: - create = false; - break; - } - } - } - - if (!UseDYLDSPI(process)) { - create = false; - } - - if (create) - return new DynamicLoaderMacOS(process); - return NULL; -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -DynamicLoaderMacOS::DynamicLoaderMacOS(Process *process) - : DynamicLoaderDarwin(process), m_image_infos_stop_id(UINT32_MAX), - m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(), - m_maybe_image_infos_address(LLDB_INVALID_ADDRESS) {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -DynamicLoaderMacOS::~DynamicLoaderMacOS() { - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->GetTarget().RemoveBreakpointByID(m_break_id); -} - -bool DynamicLoaderMacOS::ProcessDidExec() { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - bool did_exec = false; - if (m_process) { - // If we are stopped after an exec, we will have only one thread... - if (m_process->GetThreadList().GetSize() == 1) { - // Maybe we still have an image infos address around? If so see - // if that has changed, and if so we have exec'ed. - if (m_maybe_image_infos_address != LLDB_INVALID_ADDRESS) { - lldb::addr_t image_infos_address = m_process->GetImageInfoAddress(); - if (image_infos_address != m_maybe_image_infos_address) { - // We don't really have to reset this here, since we are going to - // call DoInitialImageFetch right away to handle the exec. But in - // case anybody looks at it in the meantime, it can't hurt. - m_maybe_image_infos_address = image_infos_address; - did_exec = true; - } - } - - if (!did_exec) { - // See if we are stopped at '_dyld_start' - ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0)); - if (thread_sp) { - lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); - if (frame_sp) { - const Symbol *symbol = - frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; - if (symbol) { - if (symbol->GetName() == ConstString("_dyld_start")) - did_exec = true; - } - } - } - } - } - } - - if (did_exec) { - m_libpthread_module_wp.reset(); - m_pthread_getspecific_addr.Clear(); - } - return did_exec; -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void DynamicLoaderMacOS::DoClear() { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->GetTarget().RemoveBreakpointByID(m_break_id); - - m_break_id = LLDB_INVALID_BREAK_ID; -} - -//---------------------------------------------------------------------- -// Check if we have found DYLD yet -//---------------------------------------------------------------------- -bool DynamicLoaderMacOS::DidSetNotificationBreakpoint() { - return LLDB_BREAK_ID_IS_VALID(m_break_id); -} - -void DynamicLoaderMacOS::ClearNotificationBreakpoint() { - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) { - m_process->GetTarget().RemoveBreakpointByID(m_break_id); - m_break_id = LLDB_INVALID_BREAK_ID; - } -} - -//---------------------------------------------------------------------- -// Try and figure out where dyld is by first asking the Process if it knows -// (which currently calls down in the lldb::Process to get the DYLD info -// (available on SnowLeopard only). If that fails, then check in the default -// addresses. -//---------------------------------------------------------------------- -void DynamicLoaderMacOS::DoInitialImageFetch() { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - // Remove any binaries we pre-loaded in the Target before - // launching/attaching. If the same binaries are present in the process, - // we'll get them from the shared module cache, we won't need to re-load them - // from disk. - UnloadAllImages(); - - StructuredData::ObjectSP all_image_info_json_sp( - m_process->GetLoadedDynamicLibrariesInfos()); - ImageInfo::collection image_infos; - if (all_image_info_json_sp.get() && - all_image_info_json_sp->GetAsDictionary() && - all_image_info_json_sp->GetAsDictionary()->HasKey("images") && - all_image_info_json_sp->GetAsDictionary() - ->GetValueForKey("images") - ->GetAsArray()) { - if (JSONImageInformationIntoImageInfo(all_image_info_json_sp, - image_infos)) { - if (log) - log->Printf("Initial module fetch: Adding %" PRId64 " modules.\n", - (uint64_t)image_infos.size()); - - UpdateSpecialBinariesFromNewImageInfos(image_infos); - AddModulesUsingImageInfos(image_infos); - } - } - - m_dyld_image_infos_stop_id = m_process->GetStopID(); - m_maybe_image_infos_address = m_process->GetImageInfoAddress(); -} - -bool DynamicLoaderMacOS::NeedToDoInitialImageFetch() { return true; } - -//---------------------------------------------------------------------- -// Static callback function that gets called when our DYLD notification -// breakpoint gets hit. We update all of our image infos and then let our super -// class DynamicLoader class decide if we should stop or not (based on global -// preference). -//---------------------------------------------------------------------- -bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) { - // Let the event know that the images have changed - // DYLD passes three arguments to the notification breakpoint. - // Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove - // all Arg2: unsigned long icount - Number of shared libraries - // added/removed Arg3: uint64_t mach_headers[] - Array of load addresses - // of binaries added/removed - - DynamicLoaderMacOS *dyld_instance = (DynamicLoaderMacOS *)baton; - - ExecutionContext exe_ctx(context->exe_ctx_ref); - Process *process = exe_ctx.GetProcessPtr(); - - // This is a sanity check just in case this dyld_instance is an old dyld - // plugin's breakpoint still lying around. - if (process != dyld_instance->m_process) - return false; - - if (dyld_instance->m_image_infos_stop_id != UINT32_MAX && - process->GetStopID() < dyld_instance->m_image_infos_stop_id) { - return false; - } - - const lldb::ABISP &abi = process->GetABI(); - if (abi) { - // Build up the value array to store the three arguments given above, then - // get the values from the ABI: - - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - ValueList argument_values; - - Value mode_value; // enum dyld_notify_mode { dyld_notify_adding=0, - // dyld_notify_removing=1, dyld_notify_remove_all=2 }; - Value count_value; // unsigned long count - Value headers_value; // uint64_t machHeaders[] (aka void*) - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - CompilerType clang_uint32_type = - clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( - lldb::eEncodingUint, 32); - CompilerType clang_uint64_type = - clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( - lldb::eEncodingUint, 32); - - mode_value.SetValueType(Value::eValueTypeScalar); - mode_value.SetCompilerType(clang_uint32_type); - - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 4) { - count_value.SetValueType(Value::eValueTypeScalar); - count_value.SetCompilerType(clang_uint32_type); - } else { - count_value.SetValueType(Value::eValueTypeScalar); - count_value.SetCompilerType(clang_uint64_type); - } - - headers_value.SetValueType(Value::eValueTypeScalar); - headers_value.SetCompilerType(clang_void_ptr_type); - - argument_values.PushValue(mode_value); - argument_values.PushValue(count_value); - argument_values.PushValue(headers_value); - - if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) { - uint32_t dyld_mode = - argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1); - if (dyld_mode != static_cast<uint32_t>(-1)) { - // Okay the mode was right, now get the number of elements, and the - // array of new elements... - uint32_t image_infos_count = - argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1); - if (image_infos_count != static_cast<uint32_t>(-1)) { - addr_t header_array = - argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(-1); - if (header_array != static_cast<uint64_t>(-1)) { - std::vector<addr_t> image_load_addresses; - for (uint64_t i = 0; i < image_infos_count; i++) { - Status error; - addr_t addr = process->ReadUnsignedIntegerFromMemory( - header_array + (8 * i), 8, LLDB_INVALID_ADDRESS, error); - if (addr != LLDB_INVALID_ADDRESS) { - image_load_addresses.push_back(addr); - } - } - if (dyld_mode == 0) { - // dyld_notify_adding - dyld_instance->AddBinaries(image_load_addresses); - } else if (dyld_mode == 1) { - // dyld_notify_removing - dyld_instance->UnloadImages(image_load_addresses); - } else if (dyld_mode == 2) { - // dyld_notify_remove_all - dyld_instance->UnloadAllImages(); - } - } - } - } - } - } else { - process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf( - "No ABI plugin located for triple %s -- shared libraries will not be " - "registered!\n", - process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); - } - - // Return true to stop the target, false to just let the target run - return dyld_instance->GetStopWhenImagesChange(); -} - -void DynamicLoaderMacOS::AddBinaries( - const std::vector<lldb::addr_t> &load_addresses) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ImageInfo::collection image_infos; - - if (log) - log->Printf("Adding %" PRId64 " modules.", (uint64_t)load_addresses.size()); - StructuredData::ObjectSP binaries_info_sp = - m_process->GetLoadedDynamicLibrariesInfos(load_addresses); - if (binaries_info_sp.get() && binaries_info_sp->GetAsDictionary() && - binaries_info_sp->GetAsDictionary()->HasKey("images") && - binaries_info_sp->GetAsDictionary() - ->GetValueForKey("images") - ->GetAsArray() && - binaries_info_sp->GetAsDictionary() - ->GetValueForKey("images") - ->GetAsArray() - ->GetSize() == load_addresses.size()) { - if (JSONImageInformationIntoImageInfo(binaries_info_sp, image_infos)) { - UpdateSpecialBinariesFromNewImageInfos(image_infos); - AddModulesUsingImageInfos(image_infos); - } - m_dyld_image_infos_stop_id = m_process->GetStopID(); - } -} - -// Dump the _dyld_all_image_infos members and all current image infos that we -// have parsed to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderMacOS::PutToLog(Log *log) const { - if (log == NULL) - return; -} - -bool DynamicLoaderMacOS::SetNotificationBreakpoint() { - if (m_break_id == LLDB_INVALID_BREAK_ID) { - ConstString g_symbol_name("_dyld_debugger_notification"); - const Symbol *symbol = nullptr; - ModuleSP dyld_sp(GetDYLDModule()); - if (dyld_sp) { - symbol = dyld_sp->FindFirstSymbolWithNameAndType(g_symbol_name, - eSymbolTypeCode); - } - if (symbol && - (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) { - addr_t symbol_address = - symbol->GetAddressRef().GetOpcodeLoadAddress(&m_process->GetTarget()); - if (symbol_address != LLDB_INVALID_ADDRESS) { - bool internal = true; - bool hardware = false; - Breakpoint *breakpoint = - m_process->GetTarget() - .CreateBreakpoint(symbol_address, internal, hardware) - .get(); - breakpoint->SetCallback(DynamicLoaderMacOS::NotifyBreakpointHit, this, - true); - breakpoint->SetBreakpointKind("shared-library-event"); - m_break_id = breakpoint->GetID(); - } - } - } - return m_break_id != LLDB_INVALID_BREAK_ID; -} - -addr_t -DynamicLoaderMacOS::GetDyldLockVariableAddressFromModule(Module *module) { - SymbolContext sc; - SymbolVendor *sym_vendor = module->GetSymbolVendor(); - Target &target = m_process->GetTarget(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - std::vector<uint32_t> match_indexes; - ConstString g_symbol_name("_dyld_global_lock_held"); - uint32_t num_matches = 0; - num_matches = - symtab->AppendSymbolIndexesWithName(g_symbol_name, match_indexes); - if (num_matches == 1) { - Symbol *symbol = symtab->SymbolAtIndex(match_indexes[0]); - if (symbol && - (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) { - return symbol->GetAddressRef().GetOpcodeLoadAddress(&target); - } - } - } - } - return LLDB_INVALID_ADDRESS; -} - -// Look for this symbol: -// -// int __attribute__((visibility("hidden"))) _dyld_global_lock_held = -// 0; -// -// in libdyld.dylib. -Status DynamicLoaderMacOS::CanLoadImage() { - Status error; - addr_t symbol_address = LLDB_INVALID_ADDRESS; - Target &target = m_process->GetTarget(); - const ModuleList &target_modules = target.GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - ConstString g_libdyld_name("libdyld.dylib"); - - // Find any modules named "libdyld.dylib" and look for the symbol there first - for (size_t i = 0; i < num_modules; i++) { - Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i); - if (module_pointer) { - if (module_pointer->GetFileSpec().GetFilename() == g_libdyld_name) { - symbol_address = GetDyldLockVariableAddressFromModule(module_pointer); - if (symbol_address != LLDB_INVALID_ADDRESS) - break; - } - } - } - - // Search through all modules looking for the symbol in them - if (symbol_address == LLDB_INVALID_ADDRESS) { - for (size_t i = 0; i < num_modules; i++) { - Module *module_pointer = - target_modules.GetModulePointerAtIndexUnlocked(i); - if (module_pointer) { - addr_t symbol_address = - GetDyldLockVariableAddressFromModule(module_pointer); - if (symbol_address != LLDB_INVALID_ADDRESS) - break; - } - } - } - - // Default assumption is that it is OK to load images. Only say that we - // cannot load images if we find the symbol in libdyld and it indicates that - // we cannot. - - if (symbol_address != LLDB_INVALID_ADDRESS) { - { - int lock_held = - m_process->ReadUnsignedIntegerFromMemory(symbol_address, 4, 0, error); - if (lock_held != 0) { - error.SetErrorString("dyld lock held - unsafe to load images."); - } - } - } else { - // If we were unable to find _dyld_global_lock_held in any modules, or it - // is not loaded into memory yet, we may be at process startup (sitting at - // _dyld_start) - so we should not allow dlopen calls. But if we found more - // than one module then we are clearly past _dyld_start so in that case - // we'll default to "it's safe". - if (num_modules <= 1) - error.SetErrorString("could not find the dyld library or " - "the dyld lock symbol"); - } - return error; -} - -bool DynamicLoaderMacOS::GetSharedCacheInformation( - lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache, - LazyBool &private_shared_cache) { - base_address = LLDB_INVALID_ADDRESS; - uuid.Clear(); - using_shared_cache = eLazyBoolCalculate; - private_shared_cache = eLazyBoolCalculate; - - if (m_process) { - StructuredData::ObjectSP info = m_process->GetSharedCacheInfo(); - StructuredData::Dictionary *info_dict = nullptr; - if (info.get() && info->GetAsDictionary()) { - info_dict = info->GetAsDictionary(); - } - - // {"shared_cache_base_address":140735683125248,"shared_cache_uuid - // ":"DDB8D70C- - // C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false} - - if (info_dict && info_dict->HasKey("shared_cache_uuid") && - info_dict->HasKey("no_shared_cache") && - info_dict->HasKey("shared_cache_base_address")) { - base_address = info_dict->GetValueForKey("shared_cache_base_address") - ->GetIntegerValue(LLDB_INVALID_ADDRESS); - std::string uuid_str = - info_dict->GetValueForKey("shared_cache_uuid")->GetStringValue(); - if (!uuid_str.empty()) - uuid.SetFromStringRef(uuid_str); - if (!info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue()) - using_shared_cache = eLazyBoolYes; - else - using_shared_cache = eLazyBoolNo; - if (info_dict->GetValueForKey("shared_cache_private_cache") - ->GetBooleanValue()) - private_shared_cache = eLazyBoolYes; - else - private_shared_cache = eLazyBoolNo; - - return true; - } - } - return false; -} - -void DynamicLoaderMacOS::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void DynamicLoaderMacOS::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString DynamicLoaderMacOS::GetPluginNameStatic() { - static ConstString g_name("macos-dyld"); - return g_name; -} - -const char *DynamicLoaderMacOS::GetPluginDescriptionStatic() { - return "Dynamic loader plug-in that watches for shared library loads/unloads " - "in MacOSX user processes."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString DynamicLoaderMacOS::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t DynamicLoaderMacOS::GetPluginVersion() { return 1; } diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h deleted file mode 100644 index 6303c066511c3..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- DynamicLoaderMacOS.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / -// watchOS / BridgeOS) -// platforms late 2016 and newer, where lldb will call dyld SPI functions to get -// information about shared libraries, information about the shared cache, and -// the _dyld_debugger_notification function we put a breakpoint on give us an -// array of load addresses for solibs loaded and unloaded. The SPI will tell us -// about both dyld and the executable, in addition to all of the usual solibs. - -#ifndef liblldb_DynamicLoaderMacOS_h_ -#define liblldb_DynamicLoaderMacOS_h_ - -#include <mutex> -#include <vector> - -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/UUID.h" - -#include "DynamicLoaderDarwin.h" - -class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin { -public: - DynamicLoaderMacOS(lldb_private::Process *process); - - virtual ~DynamicLoaderMacOS() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - //------------------------------------------------------------------ - /// Called after attaching a process. - /// - /// Allow DynamicLoader plug-ins to execute some code after - /// attaching to a process. - //------------------------------------------------------------------ - bool ProcessDidExec() override; - - lldb_private::Status CanLoadImage() override; - - bool GetSharedCacheInformation( - lldb::addr_t &base_address, lldb_private::UUID &uuid, - lldb_private::LazyBool &using_shared_cache, - lldb_private::LazyBool &private_shared_cache) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - void PutToLog(lldb_private::Log *log) const; - - void DoInitialImageFetch() override; - - bool NeedToDoInitialImageFetch() override; - - bool DidSetNotificationBreakpoint() override; - - void AddBinaries(const std::vector<lldb::addr_t> &load_addresses); - - void DoClear() override; - - static bool - NotifyBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - bool SetNotificationBreakpoint() override; - - void ClearNotificationBreakpoint() override; - - void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, - uint32_t infos_count, - bool update_executable); - - lldb::addr_t - GetDyldLockVariableAddressFromModule(lldb_private::Module *module); - - uint32_t m_image_infos_stop_id; // The Stop ID the last time we - // loaded/unloaded images - lldb::user_id_t m_break_id; - mutable std::recursive_mutex m_mutex; - lldb::addr_t m_maybe_image_infos_address; // If dyld is still maintaining the - // all_image_infos address, store it - // here so we can use it to detect - // exec's when talking to - // debugservers that don't support - // the "reason:exec" annotation. - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOS); -}; - -#endif // liblldb_DynamicLoaderMacOS_h_ diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp deleted file mode 100644 index ec459a783f944..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -//===-- DynamicLoaderMacOSXDYLD.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Function.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/ABI.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" - -#include "DynamicLoaderDarwin.h" -#include "DynamicLoaderMacOSXDYLD.h" - -//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#include <stdio.h> -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif - -#ifndef __APPLE__ -#include "Utility/UuidCompatibility.h" -#else -#include <uuid/uuid.h> -#endif - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process, - bool force) { - bool create = force; - if (!create) { - create = true; - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - create = (object_file->GetStrata() == ObjectFile::eStrataUser); - } - } - - if (create) { - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - create = triple_ref.getVendor() == llvm::Triple::Apple; - break; - default: - create = false; - break; - } - } - } - - if (UseDYLDSPI(process)) { - create = false; - } - - if (create) - return new DynamicLoaderMacOSXDYLD(process); - return NULL; -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD(Process *process) - : DynamicLoaderDarwin(process), - m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), - m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id(UINT32_MAX), - m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(), - m_process_image_addr_is_all_images_infos(false) {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() { - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->GetTarget().RemoveBreakpointByID(m_break_id); -} - -bool DynamicLoaderMacOSXDYLD::ProcessDidExec() { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - bool did_exec = false; - if (m_process) { - // If we are stopped after an exec, we will have only one thread... - if (m_process->GetThreadList().GetSize() == 1) { - // We know if a process has exec'ed if our "m_dyld_all_image_infos_addr" - // value differs from the Process' image info address. When a process - // execs itself it might cause a change if ASLR is enabled. - const addr_t shlib_addr = m_process->GetImageInfoAddress(); - if (m_process_image_addr_is_all_images_infos && - shlib_addr != m_dyld_all_image_infos_addr) { - // The image info address from the process is the - // 'dyld_all_image_infos' address and it has changed. - did_exec = true; - } else if (!m_process_image_addr_is_all_images_infos && - shlib_addr == m_dyld.address) { - // The image info address from the process is the mach_header address - // for dyld and it has changed. - did_exec = true; - } else { - // ASLR might be disabled and dyld could have ended up in the same - // location. We should try and detect if we are stopped at - // '_dyld_start' - ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0)); - if (thread_sp) { - lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); - if (frame_sp) { - const Symbol *symbol = - frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; - if (symbol) { - if (symbol->GetName() == ConstString("_dyld_start")) - did_exec = true; - } - } - } - } - - if (did_exec) { - m_libpthread_module_wp.reset(); - m_pthread_getspecific_addr.Clear(); - } - } - } - return did_exec; -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void DynamicLoaderMacOSXDYLD::DoClear() { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->GetTarget().RemoveBreakpointByID(m_break_id); - - m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; - m_dyld_all_image_infos.Clear(); - m_break_id = LLDB_INVALID_BREAK_ID; -} - -//---------------------------------------------------------------------- -// Check if we have found DYLD yet -//---------------------------------------------------------------------- -bool DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() { - return LLDB_BREAK_ID_IS_VALID(m_break_id); -} - -void DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint() { - if (LLDB_BREAK_ID_IS_VALID(m_break_id)) { - m_process->GetTarget().RemoveBreakpointByID(m_break_id); - } -} - -//---------------------------------------------------------------------- -// Try and figure out where dyld is by first asking the Process if it knows -// (which currently calls down in the lldb::Process to get the DYLD info -// (available on SnowLeopard only). If that fails, then check in the default -// addresses. -//---------------------------------------------------------------------- -void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() { - if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) { - // Check the image info addr as it might point to the mach header for dyld, - // or it might point to the dyld_all_image_infos struct - const addr_t shlib_addr = m_process->GetImageInfoAddress(); - if (shlib_addr != LLDB_INVALID_ADDRESS) { - ByteOrder byte_order = - m_process->GetTarget().GetArchitecture().GetByteOrder(); - uint8_t buf[4]; - DataExtractor data(buf, sizeof(buf), byte_order, 4); - Status error; - if (m_process->ReadMemory(shlib_addr, buf, 4, error) == 4) { - lldb::offset_t offset = 0; - uint32_t magic = data.GetU32(&offset); - switch (magic) { - case llvm::MachO::MH_MAGIC: - case llvm::MachO::MH_MAGIC_64: - case llvm::MachO::MH_CIGAM: - case llvm::MachO::MH_CIGAM_64: - m_process_image_addr_is_all_images_infos = false; - ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr); - return; - - default: - break; - } - } - // Maybe it points to the all image infos? - m_dyld_all_image_infos_addr = shlib_addr; - m_process_image_addr_is_all_images_infos = true; - } - } - - if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { - if (ReadAllImageInfosStructure()) { - if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) - ReadDYLDInfoFromMemoryAndSetNotificationCallback( - m_dyld_all_image_infos.dyldImageLoadAddress); - else - ReadDYLDInfoFromMemoryAndSetNotificationCallback( - m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); - return; - } - } - - // Check some default values - Module *executable = m_process->GetTarget().GetExecutableModulePointer(); - - if (executable) { - const ArchSpec &exe_arch = executable->GetArchitecture(); - if (exe_arch.GetAddressByteSize() == 8) { - ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); - } else if (exe_arch.GetMachine() == llvm::Triple::arm || - exe_arch.GetMachine() == llvm::Triple::thumb || - exe_arch.GetMachine() == llvm::Triple::aarch64) { - ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); - } else { - ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); - } - } - return; -} - -//---------------------------------------------------------------------- -// Assume that dyld is in memory at ADDR and try to parse it's load commands -//---------------------------------------------------------------------- -bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback( - lldb::addr_t addr) { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - DataExtractor data; // Load command data - static ConstString g_dyld_all_image_infos("dyld_all_image_infos"); - if (ReadMachHeader(addr, &m_dyld.header, &data)) { - if (m_dyld.header.filetype == llvm::MachO::MH_DYLINKER) { - m_dyld.address = addr; - ModuleSP dyld_module_sp; - if (ParseLoadCommands(data, m_dyld, &m_dyld.file_spec)) { - if (m_dyld.file_spec) { - UpdateDYLDImageInfoFromNewImageInfo(m_dyld); - } - } - dyld_module_sp = GetDYLDModule(); - - Target &target = m_process->GetTarget(); - - if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS && - dyld_module_sp.get()) { - const Symbol *symbol = dyld_module_sp->FindFirstSymbolWithNameAndType( - g_dyld_all_image_infos, eSymbolTypeData); - if (symbol) - m_dyld_all_image_infos_addr = symbol->GetLoadAddress(&target); - } - - // Update all image infos - InitializeFromAllImageInfos(); - - // If we didn't have an executable before, but now we do, then the dyld - // module shared pointer might be unique and we may need to add it again - // (since Target::SetExecutableModule() will clear the images). So append - // the dyld module back to the list if it is - /// unique! - if (dyld_module_sp) { - target.GetImages().AppendIfNeeded(dyld_module_sp); - - // At this point we should have read in dyld's module, and so we should - // set breakpoints in it: - ModuleList modules; - modules.Append(dyld_module_sp); - target.ModulesDidLoad(modules); - SetDYLDModule(dyld_module_sp); - } - - return true; - } - } - return false; -} - -bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() { - return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; -} - -//---------------------------------------------------------------------- -// Static callback function that gets called when our DYLD notification -// breakpoint gets hit. We update all of our image infos and then let our super -// class DynamicLoader class decide if we should stop or not (based on global -// preference). -//---------------------------------------------------------------------- -bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit( - void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) { - // Let the event know that the images have changed - // DYLD passes three arguments to the notification breakpoint. - // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing Arg2: uint32_t - // infoCount - Number of shared libraries added Arg3: dyld_image_info - // info[] - Array of structs of the form: - // const struct mach_header - // *imageLoadAddress - // const char *imageFilePath - // uintptr_t imageFileModDate (a time_t) - - DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton; - - // First step is to see if we've already initialized the all image infos. If - // we haven't then this function will do so and return true. In the course - // of initializing the all_image_infos it will read the complete current - // state, so we don't need to figure out what has changed from the data - // passed in to us. - - ExecutionContext exe_ctx(context->exe_ctx_ref); - Process *process = exe_ctx.GetProcessPtr(); - - // This is a sanity check just in case this dyld_instance is an old dyld - // plugin's breakpoint still lying around. - if (process != dyld_instance->m_process) - return false; - - if (dyld_instance->InitializeFromAllImageInfos()) - return dyld_instance->GetStopWhenImagesChange(); - - const lldb::ABISP &abi = process->GetABI(); - if (abi) { - // Build up the value array to store the three arguments given above, then - // get the values from the ABI: - - ClangASTContext *clang_ast_context = - process->GetTarget().GetScratchClangASTContext(); - ValueList argument_values; - Value input_value; - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - CompilerType clang_uint32_type = - clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( - lldb::eEncodingUint, 32); - input_value.SetValueType(Value::eValueTypeScalar); - input_value.SetCompilerType(clang_uint32_type); - // input_value.SetContext (Value::eContextTypeClangType, - // clang_uint32_type); - argument_values.PushValue(input_value); - argument_values.PushValue(input_value); - input_value.SetCompilerType(clang_void_ptr_type); - // input_value.SetContext (Value::eContextTypeClangType, - // clang_void_ptr_type); - argument_values.PushValue(input_value); - - if (abi->GetArgumentValues(exe_ctx.GetThreadRef(), argument_values)) { - uint32_t dyld_mode = - argument_values.GetValueAtIndex(0)->GetScalar().UInt(-1); - if (dyld_mode != static_cast<uint32_t>(-1)) { - // Okay the mode was right, now get the number of elements, and the - // array of new elements... - uint32_t image_infos_count = - argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1); - if (image_infos_count != static_cast<uint32_t>(-1)) { - // Got the number added, now go through the array of added elements, - // putting out the mach header address, and adding the image. Note, - // I'm not putting in logging here, since the AddModules & - // RemoveModules functions do all the logging internally. - - lldb::addr_t image_infos_addr = - argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(); - if (dyld_mode == 0) { - // This is add: - dyld_instance->AddModulesUsingImageInfosAddress(image_infos_addr, - image_infos_count); - } else { - // This is remove: - dyld_instance->RemoveModulesUsingImageInfosAddress( - image_infos_addr, image_infos_count); - } - } - } - } - } else { - process->GetTarget().GetDebugger().GetAsyncErrorStream()->Printf( - "No ABI plugin located for triple %s -- shared libraries will not be " - "registered!\n", - process->GetTarget().GetArchitecture().GetTriple().getTriple().c_str()); - } - - // Return true to stop the target, false to just let the target run - return dyld_instance->GetStopWhenImagesChange(); -} - -bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // the all image infos is already valid for this process stop ID - if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) - return true; - - m_dyld_all_image_infos.Clear(); - if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { - ByteOrder byte_order = - m_process->GetTarget().GetArchitecture().GetByteOrder(); - uint32_t addr_size = - m_process->GetTarget().GetArchitecture().GetAddressByteSize(); - - uint8_t buf[256]; - DataExtractor data(buf, sizeof(buf), byte_order, addr_size); - lldb::offset_t offset = 0; - - const size_t count_v2 = sizeof(uint32_t) + // version - sizeof(uint32_t) + // infoArrayCount - addr_size + // infoArray - addr_size + // notification - addr_size + // processDetachedFromSharedRegion + - // libSystemInitialized + pad - addr_size; // dyldImageLoadAddress - const size_t count_v11 = count_v2 + addr_size + // jitInfo - addr_size + // dyldVersion - addr_size + // errorMessage - addr_size + // terminationFlags - addr_size + // coreSymbolicationShmPage - addr_size + // systemOrderFlag - addr_size + // uuidArrayCount - addr_size + // uuidArray - addr_size + // dyldAllImageInfosAddress - addr_size + // initialImageCount - addr_size + // errorKind - addr_size + // errorClientOfDylibPath - addr_size + // errorTargetDylibPath - addr_size; // errorSymbol - const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide - sizeof(uuid_t); // sharedCacheUUID - UNUSED_IF_ASSERT_DISABLED(count_v13); - assert(sizeof(buf) >= count_v13); - - Status error; - if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) == - 4) { - m_dyld_all_image_infos.version = data.GetU32(&offset); - // If anything in the high byte is set, we probably got the byte order - // incorrect (the process might not have it set correctly yet due to - // attaching to a program without a specified file). - if (m_dyld_all_image_infos.version & 0xff000000) { - // We have guessed the wrong byte order. Swap it and try reading the - // version again. - if (byte_order == eByteOrderLittle) - byte_order = eByteOrderBig; - else - byte_order = eByteOrderLittle; - - data.SetByteOrder(byte_order); - offset = 0; - m_dyld_all_image_infos.version = data.GetU32(&offset); - } - } else { - return false; - } - - const size_t count = - (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2; - - const size_t bytes_read = - m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, count, error); - if (bytes_read == count) { - offset = 0; - m_dyld_all_image_infos.version = data.GetU32(&offset); - m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); - m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); - m_dyld_all_image_infos.notification = data.GetPointer(&offset); - m_dyld_all_image_infos.processDetachedFromSharedRegion = - data.GetU8(&offset); - m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); - // Adjust for padding. - offset += addr_size - 2; - m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); - if (m_dyld_all_image_infos.version >= 11) { - offset += addr_size * 8; - uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset); - - // When we started, we were given the actual address of the - // all_image_infos struct (probably via TASK_DYLD_INFO) in memory - - // this address is stored in m_dyld_all_image_infos_addr and is the - // most accurate address we have. - - // We read the dyld_all_image_infos struct from memory; it contains its - // own address. If the address in the struct does not match the actual - // address, the dyld we're looking at has been loaded at a different - // location (slid) from where it intended to load. The addresses in - // the dyld_all_image_infos struct are the original, non-slid - // addresses, and need to be adjusted. Most importantly the address of - // dyld and the notification address need to be adjusted. - - if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) { - uint64_t image_infos_offset = - dyld_all_image_infos_addr - - m_dyld_all_image_infos.dyldImageLoadAddress; - uint64_t notification_offset = - m_dyld_all_image_infos.notification - - m_dyld_all_image_infos.dyldImageLoadAddress; - m_dyld_all_image_infos.dyldImageLoadAddress = - m_dyld_all_image_infos_addr - image_infos_offset; - m_dyld_all_image_infos.notification = - m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; - } - } - m_dyld_all_image_infos_stop_id = m_process->GetStopID(); - return true; - } - } - return false; -} - -bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress( - lldb::addr_t image_infos_addr, uint32_t image_infos_count) { - ImageInfo::collection image_infos; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - if (log) - log->Printf("Adding %d modules.\n", image_infos_count); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - if (m_process->GetStopID() == m_dyld_image_infos_stop_id) - return true; - - StructuredData::ObjectSP image_infos_json_sp = - m_process->GetLoadedDynamicLibrariesInfos(image_infos_addr, - image_infos_count); - if (image_infos_json_sp.get() && image_infos_json_sp->GetAsDictionary() && - image_infos_json_sp->GetAsDictionary()->HasKey("images") && - image_infos_json_sp->GetAsDictionary() - ->GetValueForKey("images") - ->GetAsArray() && - image_infos_json_sp->GetAsDictionary() - ->GetValueForKey("images") - ->GetAsArray() - ->GetSize() == image_infos_count) { - bool return_value = false; - if (JSONImageInformationIntoImageInfo(image_infos_json_sp, image_infos)) { - UpdateSpecialBinariesFromNewImageInfos(image_infos); - return_value = AddModulesUsingImageInfos(image_infos); - } - m_dyld_image_infos_stop_id = m_process->GetStopID(); - return return_value; - } - - if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) - return false; - - UpdateImageInfosHeaderAndLoadCommands(image_infos, image_infos_count, false); - bool return_value = AddModulesUsingImageInfos(image_infos); - m_dyld_image_infos_stop_id = m_process->GetStopID(); - return return_value; -} - -bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress( - lldb::addr_t image_infos_addr, uint32_t image_infos_count) { - ImageInfo::collection image_infos; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - if (m_process->GetStopID() == m_dyld_image_infos_stop_id) - return true; - - // First read in the image_infos for the removed modules, and their headers & - // load commands. - if (!ReadImageInfos(image_infos_addr, image_infos_count, image_infos)) { - if (log) - log->PutCString("Failed reading image infos array."); - return false; - } - - if (log) - log->Printf("Removing %d modules.", image_infos_count); - - ModuleList unloaded_module_list; - for (uint32_t idx = 0; idx < image_infos.size(); ++idx) { - if (log) { - log->Printf("Removing module at address=0x%16.16" PRIx64 ".", - image_infos[idx].address); - image_infos[idx].PutToLog(log); - } - - // Remove this image_infos from the m_all_image_infos. We do the - // comparison by address rather than by file spec because we can have many - // modules with the same "file spec" in the case that they are modules - // loaded from memory. - // - // Also copy over the uuid from the old entry to the removed entry so we - // can use it to lookup the module in the module list. - - ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); - for (pos = m_dyld_image_infos.begin(); pos != end; pos++) { - if (image_infos[idx].address == (*pos).address) { - image_infos[idx].uuid = (*pos).uuid; - - // Add the module from this image_info to the "unloaded_module_list". - // We'll remove them all at one go later on. - - ModuleSP unload_image_module_sp( - FindTargetModuleForImageInfo(image_infos[idx], false, NULL)); - if (unload_image_module_sp.get()) { - // When we unload, be sure to use the image info from the old list, - // since that has sections correctly filled in. - UnloadModuleSections(unload_image_module_sp.get(), *pos); - unloaded_module_list.AppendIfNeeded(unload_image_module_sp); - } else { - if (log) { - log->Printf("Could not find module for unloading info entry:"); - image_infos[idx].PutToLog(log); - } - } - - // Then remove it from the m_dyld_image_infos: - - m_dyld_image_infos.erase(pos); - break; - } - } - - if (pos == end) { - if (log) { - log->Printf("Could not find image_info entry for unloading image:"); - image_infos[idx].PutToLog(log); - } - } - } - if (unloaded_module_list.GetSize() > 0) { - if (log) { - log->PutCString("Unloaded:"); - unloaded_module_list.LogUUIDAndPaths( - log, "DynamicLoaderMacOSXDYLD::ModulesDidUnload"); - } - m_process->GetTarget().GetImages().Remove(unloaded_module_list); - } - m_dyld_image_infos_stop_id = m_process->GetStopID(); - return true; -} - -bool DynamicLoaderMacOSXDYLD::ReadImageInfos( - lldb::addr_t image_infos_addr, uint32_t image_infos_count, - ImageInfo::collection &image_infos) { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - const ByteOrder endian = GetByteOrderFromMagic(m_dyld.header.magic); - const uint32_t addr_size = m_dyld.GetAddressByteSize(); - - image_infos.resize(image_infos_count); - const size_t count = image_infos.size() * 3 * addr_size; - DataBufferHeap info_data(count, 0); - Status error; - const size_t bytes_read = m_process->ReadMemory( - image_infos_addr, info_data.GetBytes(), info_data.GetByteSize(), error); - if (bytes_read == count) { - lldb::offset_t info_data_offset = 0; - DataExtractor info_data_ref(info_data.GetBytes(), info_data.GetByteSize(), - endian, addr_size); - for (size_t i = 0; - i < image_infos.size() && info_data_ref.ValidOffset(info_data_offset); - i++) { - image_infos[i].address = info_data_ref.GetPointer(&info_data_offset); - lldb::addr_t path_addr = info_data_ref.GetPointer(&info_data_offset); - image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset); - - char raw_path[PATH_MAX]; - m_process->ReadCStringFromMemory(path_addr, raw_path, sizeof(raw_path), - error); - // don't resolve the path - if (error.Success()) { - image_infos[i].file_spec.SetFile(raw_path, FileSpec::Style::native); - } - } - return true; - } else { - return false; - } -} - -//---------------------------------------------------------------------- -// If we have found where the "_dyld_all_image_infos" lives in memory, read the -// current info from it, and then update all image load addresses (or lack -// thereof). Only do this if this is the first time we're reading the dyld -// infos. Return true if we actually read anything, and false otherwise. -//---------------------------------------------------------------------- -bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - if (m_process->GetStopID() == m_dyld_image_infos_stop_id || - m_dyld_image_infos.size() != 0) - return false; - - if (ReadAllImageInfosStructure()) { - // Nothing to load or unload? - if (m_dyld_all_image_infos.dylib_info_count == 0) - return true; - - if (m_dyld_all_image_infos.dylib_info_addr == 0) { - // DYLD is updating the images now. So we should say we have no images, - // and then we'll - // figure it out when we hit the added breakpoint. - return false; - } else { - if (!AddModulesUsingImageInfosAddress( - m_dyld_all_image_infos.dylib_info_addr, - m_dyld_all_image_infos.dylib_info_count)) { - DEBUG_PRINTF("%s", "unable to read all data for all_dylib_infos."); - m_dyld_image_infos.clear(); - } - } - - // Now we have one more bit of business. If there is a library left in the - // images for our target that doesn't have a load address, then it must be - // something that we were expecting to load (for instance we read a load - // command for it) but it didn't in fact load - probably because - // DYLD_*_PATH pointed to an equivalent version. We don't want it to stay - // in the target's module list or it will confuse us, so unload it here. - Target &target = m_process->GetTarget(); - const ModuleList &target_modules = target.GetImages(); - ModuleList not_loaded_modules; - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - - size_t num_modules = target_modules.GetSize(); - for (size_t i = 0; i < num_modules; i++) { - ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i); - if (!module_sp->IsLoadedInTarget(&target)) { - if (log) { - StreamString s; - module_sp->GetDescription(&s); - log->Printf("Unloading pre-run module: %s.", s.GetData()); - } - not_loaded_modules.Append(module_sp); - } - } - - if (not_loaded_modules.GetSize() != 0) { - target.GetImages().Remove(not_loaded_modules); - } - - return true; - } else - return false; -} - -//---------------------------------------------------------------------- -// Read a mach_header at ADDR into HEADER, and also fill in the load command -// data into LOAD_COMMAND_DATA if it is non-NULL. -// -// Returns true if we succeed, false if we fail for any reason. -//---------------------------------------------------------------------- -bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr, - llvm::MachO::mach_header *header, - DataExtractor *load_command_data) { - DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); - Status error; - size_t bytes_read = m_process->ReadMemory(addr, header_bytes.GetBytes(), - header_bytes.GetByteSize(), error); - if (bytes_read == sizeof(llvm::MachO::mach_header)) { - lldb::offset_t offset = 0; - ::memset(header, 0, sizeof(llvm::MachO::mach_header)); - - // Get the magic byte unswapped so we can figure out what we are dealing - // with - DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), - endian::InlHostByteOrder(), 4); - header->magic = data.GetU32(&offset); - lldb::addr_t load_cmd_addr = addr; - data.SetByteOrder( - DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header->magic)); - switch (header->magic) { - case llvm::MachO::MH_MAGIC: - case llvm::MachO::MH_CIGAM: - data.SetAddressByteSize(4); - load_cmd_addr += sizeof(llvm::MachO::mach_header); - break; - - case llvm::MachO::MH_MAGIC_64: - case llvm::MachO::MH_CIGAM_64: - data.SetAddressByteSize(8); - load_cmd_addr += sizeof(llvm::MachO::mach_header_64); - break; - - default: - return false; - } - - // Read the rest of dyld's mach header - if (data.GetU32(&offset, &header->cputype, - (sizeof(llvm::MachO::mach_header) / sizeof(uint32_t)) - - 1)) { - if (load_command_data == NULL) - return true; // We were able to read the mach_header and weren't asked - // to read the load command bytes - - DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); - - size_t load_cmd_bytes_read = - m_process->ReadMemory(load_cmd_addr, load_cmd_data_sp->GetBytes(), - load_cmd_data_sp->GetByteSize(), error); - - if (load_cmd_bytes_read == header->sizeofcmds) { - // Set the load command data and also set the correct endian swap - // settings and the correct address size - load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); - load_command_data->SetByteOrder(data.GetByteOrder()); - load_command_data->SetAddressByteSize(data.GetAddressByteSize()); - return true; // We successfully read the mach_header and the load - // command data - } - - return false; // We weren't able to read the load command data - } - } - return false; // We failed the read the mach_header -} - -//---------------------------------------------------------------------- -// Parse the load commands for an image -//---------------------------------------------------------------------- -uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data, - ImageInfo &dylib_info, - FileSpec *lc_id_dylinker) { - lldb::offset_t offset = 0; - uint32_t cmd_idx; - Segment segment; - dylib_info.Clear(true); - - for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) { - // Clear out any load command specific data from DYLIB_INFO since we are - // about to read it. - - if (data.ValidOffsetForDataOfSize(offset, - sizeof(llvm::MachO::load_command))) { - llvm::MachO::load_command load_cmd; - lldb::offset_t load_cmd_offset = offset; - load_cmd.cmd = data.GetU32(&offset); - load_cmd.cmdsize = data.GetU32(&offset); - switch (load_cmd.cmd) { - case llvm::MachO::LC_SEGMENT: { - segment.name.SetTrimmedCStringWithLength( - (const char *)data.GetData(&offset, 16), 16); - // We are putting 4 uint32_t values 4 uint64_t values so we have to use - // multiple 32 bit gets below. - segment.vmaddr = data.GetU32(&offset); - segment.vmsize = data.GetU32(&offset); - segment.fileoff = data.GetU32(&offset); - segment.filesize = data.GetU32(&offset); - // Extract maxprot, initprot, nsects and flags all at once - data.GetU32(&offset, &segment.maxprot, 4); - dylib_info.segments.push_back(segment); - } break; - - case llvm::MachO::LC_SEGMENT_64: { - segment.name.SetTrimmedCStringWithLength( - (const char *)data.GetData(&offset, 16), 16); - // Extract vmaddr, vmsize, fileoff, and filesize all at once - data.GetU64(&offset, &segment.vmaddr, 4); - // Extract maxprot, initprot, nsects and flags all at once - data.GetU32(&offset, &segment.maxprot, 4); - dylib_info.segments.push_back(segment); - } break; - - case llvm::MachO::LC_ID_DYLINKER: - if (lc_id_dylinker) { - const lldb::offset_t name_offset = - load_cmd_offset + data.GetU32(&offset); - const char *path = data.PeekCStr(name_offset); - lc_id_dylinker->SetFile(path, FileSpec::Style::native); - FileSystem::Instance().Resolve(*lc_id_dylinker); - } - break; - - case llvm::MachO::LC_UUID: - dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16); - break; - - default: - break; - } - // Set offset to be the beginning of the next load command. - offset = load_cmd_offset + load_cmd.cmdsize; - } - } - - // All sections listed in the dyld image info structure will all either be - // fixed up already, or they will all be off by a single slide amount that is - // determined by finding the first segment that is at file offset zero which - // also has bytes (a file size that is greater than zero) in the object file. - - // Determine the slide amount (if any) - const size_t num_sections = dylib_info.segments.size(); - for (size_t i = 0; i < num_sections; ++i) { - // Iterate through the object file sections to find the first section that - // starts of file offset zero and that has bytes in the file... - if ((dylib_info.segments[i].fileoff == 0 && - dylib_info.segments[i].filesize > 0) || - (dylib_info.segments[i].name == ConstString("__TEXT"))) { - dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr; - // We have found the slide amount, so we can exit this for loop. - break; - } - } - return cmd_idx; -} - -//---------------------------------------------------------------------- -// Read the mach_header and load commands for each image that the -// _dyld_all_image_infos structure points to and cache the results. -//---------------------------------------------------------------------- - -void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands( - ImageInfo::collection &image_infos, uint32_t infos_count, - bool update_executable) { - uint32_t exe_idx = UINT32_MAX; - // Read any UUID values that we can get - for (uint32_t i = 0; i < infos_count; i++) { - if (!image_infos[i].UUIDValid()) { - DataExtractor data; // Load command data - if (!ReadMachHeader(image_infos[i].address, &image_infos[i].header, - &data)) - continue; - - ParseLoadCommands(data, image_infos[i], NULL); - - if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) - exe_idx = i; - } - } - - Target &target = m_process->GetTarget(); - - if (exe_idx < image_infos.size()) { - const bool can_create = true; - ModuleSP exe_module_sp( - FindTargetModuleForImageInfo(image_infos[exe_idx], can_create, NULL)); - - if (exe_module_sp) { - UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]); - - if (exe_module_sp.get() != target.GetExecutableModulePointer()) { - // Don't load dependent images since we are in dyld where we will know - // and find out about all images that are loaded. Also when setting the - // executable module, it will clear the targets module list, and if we - // have an in memory dyld module, it will get removed from the list so - // we will need to add it back after setting the executable module, so - // we first try and see if we already have a weak pointer to the dyld - // module, make it into a shared pointer, then add the executable, then - // re-add it back to make sure it is always in the list. - ModuleSP dyld_module_sp(GetDYLDModule()); - - m_process->GetTarget().SetExecutableModule(exe_module_sp, - eLoadDependentsNo); - - if (dyld_module_sp) { - if (target.GetImages().AppendIfNeeded(dyld_module_sp)) { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - - // Also add it to the section list. - UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); - } - } - } - } - } -} - -//---------------------------------------------------------------------- -// Dump the _dyld_all_image_infos members and all current image infos that we -// have parsed to the file handle provided. -//---------------------------------------------------------------------- -void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const { - if (log == NULL) - return; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - log->Printf( - "dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64 - ", notify=0x%8.8" PRIx64 " }", - m_dyld_all_image_infos.version, m_dyld_all_image_infos.dylib_info_count, - (uint64_t)m_dyld_all_image_infos.dylib_info_addr, - (uint64_t)m_dyld_all_image_infos.notification); - size_t i; - const size_t count = m_dyld_image_infos.size(); - if (count > 0) { - log->PutCString("Loaded:"); - for (i = 0; i < count; i++) - m_dyld_image_infos[i].PutToLog(log); - } -} - -bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() { - DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", - __FUNCTION__, StateAsCString(m_process->GetState())); - if (m_break_id == LLDB_INVALID_BREAK_ID) { - if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) { - Address so_addr; - // Set the notification breakpoint and install a breakpoint callback - // function that will get called each time the breakpoint gets hit. We - // will use this to track when shared libraries get loaded/unloaded. - bool resolved = m_process->GetTarget().ResolveLoadAddress( - m_dyld_all_image_infos.notification, so_addr); - if (!resolved) { - ModuleSP dyld_module_sp = GetDYLDModule(); - if (dyld_module_sp) { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - - UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); - resolved = m_process->GetTarget().ResolveLoadAddress( - m_dyld_all_image_infos.notification, so_addr); - } - } - - if (resolved) { - Breakpoint *dyld_break = - m_process->GetTarget().CreateBreakpoint(so_addr, true, false).get(); - dyld_break->SetCallback(DynamicLoaderMacOSXDYLD::NotifyBreakpointHit, - this, true); - dyld_break->SetBreakpointKind("shared-library-event"); - m_break_id = dyld_break->GetID(); - } - } - } - return m_break_id != LLDB_INVALID_BREAK_ID; -} - -Status DynamicLoaderMacOSXDYLD::CanLoadImage() { - Status error; - // In order for us to tell if we can load a shared library we verify that the - // dylib_info_addr isn't zero (which means no shared libraries have been set - // yet, or dyld is currently mucking with the shared library list). - if (ReadAllImageInfosStructure()) { - // TODO: also check the _dyld_global_lock_held variable in - // libSystem.B.dylib? - // TODO: check the malloc lock? - // TODO: check the objective C lock? - if (m_dyld_all_image_infos.dylib_info_addr != 0) - return error; // Success - } - - error.SetErrorString("unsafe to load or unload shared libraries"); - return error; -} - -bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation( - lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache, - LazyBool &private_shared_cache) { - base_address = LLDB_INVALID_ADDRESS; - uuid.Clear(); - using_shared_cache = eLazyBoolCalculate; - private_shared_cache = eLazyBoolCalculate; - - if (m_process) { - addr_t all_image_infos = m_process->GetImageInfoAddress(); - - // The address returned by GetImageInfoAddress may be the address of dyld - // (don't want) or it may be the address of the dyld_all_image_infos - // structure (want). The first four bytes will be either the version field - // (all_image_infos) or a Mach-O file magic constant. Version 13 and higher - // of dyld_all_image_infos is required to get the sharedCacheUUID field. - - Status err; - uint32_t version_or_magic = - m_process->ReadUnsignedIntegerFromMemory(all_image_infos, 4, -1, err); - if (version_or_magic != static_cast<uint32_t>(-1) && - version_or_magic != llvm::MachO::MH_MAGIC && - version_or_magic != llvm::MachO::MH_CIGAM && - version_or_magic != llvm::MachO::MH_MAGIC_64 && - version_or_magic != llvm::MachO::MH_CIGAM_64 && - version_or_magic >= 13) { - addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS; - int wordsize = m_process->GetAddressByteSize(); - if (wordsize == 8) { - sharedCacheUUID_address = - all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h> - } - if (wordsize == 4) { - sharedCacheUUID_address = - all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h> - } - if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) { - uuid_t shared_cache_uuid; - if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid, - sizeof(uuid_t), err) == sizeof(uuid_t)) { - uuid = UUID::fromOptionalData(shared_cache_uuid, 16); - if (uuid.IsValid()) { - using_shared_cache = eLazyBoolYes; - } - } - - if (version_or_magic >= 15) { - // The sharedCacheBaseAddress field is the next one in the - // dyld_all_image_infos struct. - addr_t sharedCacheBaseAddr_address = sharedCacheUUID_address + 16; - Status error; - base_address = m_process->ReadUnsignedIntegerFromMemory( - sharedCacheBaseAddr_address, wordsize, LLDB_INVALID_ADDRESS, - error); - if (error.Fail()) - base_address = LLDB_INVALID_ADDRESS; - } - - return true; - } - - // - // add - // NB: sharedCacheBaseAddress is the next field in dyld_all_image_infos - // after - // sharedCacheUUID -- that is, 16 bytes after it, if we wanted to fetch - // it. - } - } - return false; -} - -void DynamicLoaderMacOSXDYLD::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void DynamicLoaderMacOSXDYLD::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString DynamicLoaderMacOSXDYLD::GetPluginNameStatic() { - static ConstString g_name("macosx-dyld"); - return g_name; -} - -const char *DynamicLoaderMacOSXDYLD::GetPluginDescriptionStatic() { - return "Dynamic loader plug-in that watches for shared library loads/unloads " - "in MacOSX user processes."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString DynamicLoaderMacOSXDYLD::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t DynamicLoaderMacOSXDYLD::GetPluginVersion() { return 1; } - -uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() { - std::lock_guard<std::recursive_mutex> baseclass_guard(GetMutex()); - - switch (m_dyld.header.magic) { - case llvm::MachO::MH_MAGIC: - case llvm::MachO::MH_CIGAM: - return 4; - - case llvm::MachO::MH_MAGIC_64: - case llvm::MachO::MH_CIGAM_64: - return 8; - - default: - break; - } - return 0; -} - -lldb::ByteOrder DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) { - switch (magic) { - case llvm::MachO::MH_MAGIC: - case llvm::MachO::MH_MAGIC_64: - return endian::InlHostByteOrder(); - - case llvm::MachO::MH_CIGAM: - case llvm::MachO::MH_CIGAM_64: - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - return lldb::eByteOrderLittle; - else - return lldb::eByteOrderBig; - - default: - break; - } - return lldb::eByteOrderInvalid; -} diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h deleted file mode 100644 index 3dc0f15bddf74..0000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ /dev/null @@ -1,182 +0,0 @@ -//===-- DynamicLoaderMacOSXDYLD.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS / -// watchOS / BridgeOS) -// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos" -// dyld internal structure to understand where things were loaded and the -// solib loaded/unloaded notification function we put a breakpoint on gives us -// an array of (load address, mod time, file path) tuples. -// -// As of late 2016, the new DynamicLoaderMacOS plugin should be used, which uses -// dyld SPI functions to get the same information without reading internal dyld -// data structures. - -#ifndef liblldb_DynamicLoaderMacOSXDYLD_h_ -#define liblldb_DynamicLoaderMacOSXDYLD_h_ - -#include <mutex> -#include <vector> - -#include "lldb/Host/SafeMachO.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/UUID.h" - -#include "DynamicLoaderDarwin.h" - -class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { -public: - DynamicLoaderMacOSXDYLD(lldb_private::Process *process); - - virtual ~DynamicLoaderMacOSXDYLD() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - //------------------------------------------------------------------ - /// Called after attaching a process. - /// - /// Allow DynamicLoader plug-ins to execute some code after - /// attaching to a process. - //------------------------------------------------------------------ - bool ProcessDidExec() override; - - lldb_private::Status CanLoadImage() override; - - bool GetSharedCacheInformation( - lldb::addr_t &base_address, lldb_private::UUID &uuid, - lldb_private::LazyBool &using_shared_cache, - lldb_private::LazyBool &private_shared_cache) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - void PutToLog(lldb_private::Log *log) const; - - void DoInitialImageFetch() override; - - bool NeedToDoInitialImageFetch() override; - - bool DidSetNotificationBreakpoint() override; - - void DoClear() override; - - bool ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr); - - static bool - NotifyBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, lldb::user_id_t break_loc_id); - - uint32_t AddrByteSize(); - - bool ReadMachHeader(lldb::addr_t addr, llvm::MachO::mach_header *header, - lldb_private::DataExtractor *load_command_data); - - uint32_t ParseLoadCommands(const lldb_private::DataExtractor &data, - ImageInfo &dylib_info, - lldb_private::FileSpec *lc_id_dylinker); - - struct DYLDAllImageInfos { - uint32_t version; - uint32_t dylib_info_count; // Version >= 1 - lldb::addr_t dylib_info_addr; // Version >= 1 - lldb::addr_t notification; // Version >= 1 - bool processDetachedFromSharedRegion; // Version >= 1 - bool libSystemInitialized; // Version >= 2 - lldb::addr_t dyldImageLoadAddress; // Version >= 2 - - DYLDAllImageInfos() - : version(0), dylib_info_count(0), - dylib_info_addr(LLDB_INVALID_ADDRESS), - notification(LLDB_INVALID_ADDRESS), - processDetachedFromSharedRegion(false), libSystemInitialized(false), - dyldImageLoadAddress(LLDB_INVALID_ADDRESS) {} - - void Clear() { - version = 0; - dylib_info_count = 0; - dylib_info_addr = LLDB_INVALID_ADDRESS; - notification = LLDB_INVALID_ADDRESS; - processDetachedFromSharedRegion = false; - libSystemInitialized = false; - dyldImageLoadAddress = LLDB_INVALID_ADDRESS; - } - - bool IsValid() const { return version >= 1 || version <= 6; } - }; - - static lldb::ByteOrder GetByteOrderFromMagic(uint32_t magic); - - bool SetNotificationBreakpoint() override; - - void ClearNotificationBreakpoint() override; - - // There is a little tricky bit where you might initially attach while dyld is - // updating - // the all_image_infos, and you can't read the infos, so you have to continue - // and pick it - // up when you hit the update breakpoint. At that point, you need to run this - // initialize - // function, but when you do it that way you DON'T need to do the extra work - // you would at - // the breakpoint. - // So this function will only do actual work if the image infos haven't been - // read yet. - // If it does do any work, then it will return true, and false otherwise. - // That way you can - // call it in the breakpoint action, and if it returns true you're done. - bool InitializeFromAllImageInfos(); - - bool ReadAllImageInfosStructure(); - - bool AddModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, - uint32_t image_infos_count); - - bool RemoveModulesUsingImageInfosAddress(lldb::addr_t image_infos_addr, - uint32_t image_infos_count); - - void UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, - uint32_t infos_count, - bool update_executable); - - bool ReadImageInfos(lldb::addr_t image_infos_addr, uint32_t image_infos_count, - ImageInfo::collection &image_infos); - - lldb::addr_t m_dyld_all_image_infos_addr; - DYLDAllImageInfos m_dyld_all_image_infos; - uint32_t m_dyld_all_image_infos_stop_id; - lldb::user_id_t m_break_id; - mutable std::recursive_mutex m_mutex; - bool m_process_image_addr_is_all_images_infos; - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOSXDYLD); -}; - -#endif // liblldb_DynamicLoaderMacOSXDYLD_h_ diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt b/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt deleted file mode 100644 index 409ba92a0e19c..0000000000000 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN - AuxVector.cpp - DYLDRendezvous.cpp - DynamicLoaderPOSIXDYLD.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbPluginProcessElfCore - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/DynamicLoader/Static/CMakeLists.txt b/source/Plugins/DynamicLoader/Static/CMakeLists.txt deleted file mode 100644 index be54a30534705..0000000000000 --- a/source/Plugins/DynamicLoader/Static/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderStatic PLUGIN - DynamicLoaderStatic.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - ) diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/CMakeLists.txt b/source/Plugins/DynamicLoader/Windows-DYLD/CMakeLists.txt deleted file mode 100644 index 7557ada514662..0000000000000 --- a/source/Plugins/DynamicLoader/Windows-DYLD/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginDynamicLoaderWindowsDYLD PLUGIN - DynamicLoaderWindowsDYLD.cpp - - LINK_LIBS - lldbCore - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ExpressionParser/CMakeLists.txt b/source/Plugins/ExpressionParser/CMakeLists.txt deleted file mode 100644 index 17c40aee44cc2..0000000000000 --- a/source/Plugins/ExpressionParser/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(Clang) diff --git a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/source/Plugins/ExpressionParser/Clang/CMakeLists.txt deleted file mode 100644 index ec4f6d5674e11..0000000000000 --- a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -if(NOT LLDB_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - -add_lldb_library(lldbPluginExpressionParserClang PLUGIN - ASTDumper.cpp - ASTResultSynthesizer.cpp - ASTStructExtractor.cpp - ClangASTSource.cpp - ClangExpressionDeclMap.cpp - ClangExpressionParser.cpp - ClangExpressionVariable.cpp - ClangFunctionCaller.cpp - ClangHost.cpp - ClangModulesDeclVendor.cpp - ClangPersistentVariables.cpp - ClangUserExpression.cpp - ClangUtilityFunction.cpp - IRForTarget.cpp - - DEPENDS - ${tablegen_deps} - - LINK_LIBS - clangAST - clangCodeGen - clangDriver - clangEdit - clangFrontend - clangLex - clangParse - clangRewrite - clangRewriteFrontend - clangSema - clangSerialization - lldbCore - lldbExpression - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginCPlusPlusLanguage - LINK_COMPONENTS - Core - ExecutionEngine - ipo - MCJIT - Support - ) diff --git a/source/Plugins/Instruction/ARM/CMakeLists.txt b/source/Plugins/Instruction/ARM/CMakeLists.txt deleted file mode 100644 index 24f803db3d0e2..0000000000000 --- a/source/Plugins/Instruction/ARM/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_lldb_library(lldbPluginInstructionARM PLUGIN - EmulateInstructionARM.cpp - EmulationStateARM.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Instruction/ARM64/CMakeLists.txt b/source/Plugins/Instruction/ARM64/CMakeLists.txt deleted file mode 100644 index effe0e3bfe660..0000000000000 --- a/source/Plugins/Instruction/ARM64/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginInstructionARM64 PLUGIN - EmulateInstructionARM64.cpp - - LINK_LIBS - lldbCore - lldbInterpreter - lldbSymbol - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Instruction/CMakeLists.txt b/source/Plugins/Instruction/CMakeLists.txt deleted file mode 100644 index 89771e8f46d14..0000000000000 --- a/source/Plugins/Instruction/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory(ARM) -add_subdirectory(ARM64) -add_subdirectory(MIPS) -add_subdirectory(MIPS64) -add_subdirectory(PPC64) diff --git a/source/Plugins/Instruction/MIPS/CMakeLists.txt b/source/Plugins/Instruction/MIPS/CMakeLists.txt deleted file mode 100644 index b2fe0ee8813f0..0000000000000 --- a/source/Plugins/Instruction/MIPS/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -if(Mips IN_LIST LLVM_TARGETS_TO_BUILD) - set(mips_target Mips) -endif() - -add_lldb_library(lldbPluginInstructionMIPS PLUGIN - EmulateInstructionMIPS.cpp - - LINK_LIBS - lldbCore - lldbInterpreter - lldbSymbol - lldbTarget - lldbPluginProcessUtility - LINK_COMPONENTS - MC - Support - ${mips_target} - ) diff --git a/source/Plugins/Instruction/MIPS64/CMakeLists.txt b/source/Plugins/Instruction/MIPS64/CMakeLists.txt deleted file mode 100644 index ddb964bf50a59..0000000000000 --- a/source/Plugins/Instruction/MIPS64/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -if(Mips IN_LIST LLVM_TARGETS_TO_BUILD) - set(mips_target Mips) -endif() - -add_lldb_library(lldbPluginInstructionMIPS64 PLUGIN - EmulateInstructionMIPS64.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbPluginProcessUtility - LINK_COMPONENTS - MC - Support - ${mips_target} - ) diff --git a/source/Plugins/Instruction/PPC64/CMakeLists.txt b/source/Plugins/Instruction/PPC64/CMakeLists.txt deleted file mode 100644 index 0926433fc77cf..0000000000000 --- a/source/Plugins/Instruction/PPC64/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginInstructionPPC64 PLUGIN - EmulateInstructionPPC64.cpp - - LINK_LIBS - lldbCore - lldbInterpreter - lldbSymbol - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt deleted file mode 100644 index dc7464fd1939f..0000000000000 --- a/source/Plugins/InstrumentationRuntime/ASan/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginInstrumentationRuntimeASan PLUGIN - ASanRuntime.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbInterpreter - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/InstrumentationRuntime/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/CMakeLists.txt deleted file mode 100644 index 55e8752e74242..0000000000000 --- a/source/Plugins/InstrumentationRuntime/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_subdirectory(ASan) -add_subdirectory(MainThreadChecker) -add_subdirectory(TSan) -add_subdirectory(UBSan) diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/MainThreadChecker/CMakeLists.txt deleted file mode 100644 index 440b176b27092..0000000000000 --- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginInstrumentationRuntimeMainThreadChecker PLUGIN - MainThreadCheckerRuntime.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbInterpreter - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/InstrumentationRuntime/TSan/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/TSan/CMakeLists.txt deleted file mode 100644 index 4dcd34131b8eb..0000000000000 --- a/source/Plugins/InstrumentationRuntime/TSan/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_lldb_library(lldbPluginInstrumentationRuntimeTSan PLUGIN - TSanRuntime.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbInterpreter - lldbSymbol - lldbTarget - lldbPluginProcessUtility - ) diff --git a/source/Plugins/InstrumentationRuntime/UBSan/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/UBSan/CMakeLists.txt deleted file mode 100644 index 984bf86f83b5c..0000000000000 --- a/source/Plugins/InstrumentationRuntime/UBSan/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginInstrumentationRuntimeUBSan PLUGIN - UBSanRuntime.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbInterpreter - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/JITLoader/CMakeLists.txt b/source/Plugins/JITLoader/CMakeLists.txt deleted file mode 100644 index e52230199109f..0000000000000 --- a/source/Plugins/JITLoader/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(GDB) diff --git a/source/Plugins/JITLoader/GDB/CMakeLists.txt b/source/Plugins/JITLoader/GDB/CMakeLists.txt deleted file mode 100644 index 190599cbd588f..0000000000000 --- a/source/Plugins/JITLoader/GDB/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_lldb_library(lldbPluginJITLoaderGDB PLUGIN - JITLoaderGDB.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) - diff --git a/source/Plugins/Language/CMakeLists.txt b/source/Plugins/Language/CMakeLists.txt deleted file mode 100644 index 7869074566d1e..0000000000000 --- a/source/Plugins/Language/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_subdirectory(ClangCommon) -add_subdirectory(CPlusPlus) -add_subdirectory(ObjC) -add_subdirectory(ObjCPlusPlus) diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt deleted file mode 100644 index bc357aa52b849..0000000000000 --- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN - BlockPointer.cpp - CPlusPlusLanguage.cpp - CPlusPlusNameParser.cpp - CxxStringTypes.cpp - LibCxx.cpp - LibCxxAtomic.cpp - LibCxxBitset.cpp - LibCxxInitializerList.cpp - LibCxxList.cpp - LibCxxMap.cpp - LibCxxOptional.cpp - LibCxxQueue.cpp - LibCxxTuple.cpp - LibCxxUnorderedMap.cpp - LibCxxVariant.cpp - LibCxxVector.cpp - LibStdcpp.cpp - LibStdcppTuple.cpp - LibStdcppUniquePointer.cpp - MSVCUndecoratedNameParser.cpp - - LINK_LIBS - lldbCore - lldbDataFormatters - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginClangCommon - - LINK_COMPONENTS - Support -) diff --git a/source/Plugins/Language/ClangCommon/CMakeLists.txt b/source/Plugins/Language/ClangCommon/CMakeLists.txt deleted file mode 100644 index 854320dd312ec..0000000000000 --- a/source/Plugins/Language/ClangCommon/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginClangCommon PLUGIN - ClangHighlighter.cpp - - LINK_LIBS - lldbCore - lldbUtility - LINK_COMPONENTS - Support -) diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt deleted file mode 100644 index afb68d4de8319..0000000000000 --- a/source/Plugins/Language/ObjC/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set(EXTRA_CXXFLAGS "") - -if (CXX_SUPPORTS_NO_GNU_ANONYMOUS_STRUCT) - set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-gnu-anonymous-struct) -endif () - -if (CXX_SUPPORTS_NO_NESTED_ANON_TYPES) - set(EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -Wno-nested-anon-types) -endif () - -add_lldb_library(lldbPluginObjCLanguage PLUGIN - ObjCLanguage.cpp - CF.cpp - Cocoa.cpp - CoreMedia.cpp - NSArray.cpp - NSDictionary.cpp - NSError.cpp - NSException.cpp - NSIndexPath.cpp - NSSet.cpp - NSString.cpp - - LINK_LIBS - clangAST - lldbCore - lldbDataFormatters - lldbExpression - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginAppleObjCRuntime - lldbPluginClangCommon - - EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} -) diff --git a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt b/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt deleted file mode 100644 index 1aa5cc1ed4882..0000000000000 --- a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_lldb_library(lldbPluginObjCPlusPlusLanguage PLUGIN - ObjCPlusPlusLanguage.cpp - - LINK_LIBS - lldbCore - lldbTarget - lldbPluginClangCommon -) diff --git a/source/Plugins/LanguageRuntime/CMakeLists.txt b/source/Plugins/LanguageRuntime/CMakeLists.txt deleted file mode 100644 index c62791445a9a2..0000000000000 --- a/source/Plugins/LanguageRuntime/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_subdirectory(CPlusPlus) -add_subdirectory(ObjC) -add_subdirectory(RenderScript) diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt b/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt deleted file mode 100644 index 26c68c60b0198..0000000000000 --- a/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(ItaniumABI) -#add_subdirectory(MicrosoftABI) diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt deleted file mode 100644 index 14d1f46caebb9..0000000000000 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginCXXItaniumABI PLUGIN - ItaniumABILanguageRuntime.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbInterpreter - lldbSymbol - lldbTarget - ) diff --git a/source/Plugins/LanguageRuntime/Go/CMakeLists.txt b/source/Plugins/LanguageRuntime/Go/CMakeLists.txt deleted file mode 100644 index 62418def58f63..0000000000000 --- a/source/Plugins/LanguageRuntime/Go/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginLanguageRuntimeGo PLUGIN - LINK_LIBS - lldbBreakpoint - lldbCore - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt deleted file mode 100644 index 18f3ae1c5b1e3..0000000000000 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_lldb_library(lldbPluginAppleObjCRuntime PLUGIN - AppleObjCRuntime.cpp - AppleObjCRuntimeV1.cpp - AppleObjCRuntimeV2.cpp - AppleObjCTrampolineHandler.cpp - AppleObjCDeclVendor.cpp - AppleThreadPlanStepThroughObjCTrampoline.cpp - AppleObjCClassDescriptorV2.cpp - AppleObjCTypeEncodingParser.cpp - - LINK_LIBS - clangAST - lldbBreakpoint - lldbCore - lldbExpression - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginExpressionParserClang - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt b/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt deleted file mode 100644 index af13dc6a144de..0000000000000 --- a/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(AppleObjCRuntime) diff --git a/source/Plugins/LanguageRuntime/RenderScript/CMakeLists.txt b/source/Plugins/LanguageRuntime/RenderScript/CMakeLists.txt deleted file mode 100644 index d944d76c49578..0000000000000 --- a/source/Plugins/LanguageRuntime/RenderScript/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(RenderScriptRuntime) diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt deleted file mode 100644 index 1a6c499461340..0000000000000 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -if(NOT LLDB_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - - -add_lldb_library(lldbPluginRenderScriptRuntime PLUGIN - RenderScriptRuntime.cpp - RenderScriptExpressionOpts.cpp - RenderScriptx86ABIFixups.cpp - RenderScriptScriptGroup.cpp - - DEPENDS - ${tablegen_deps} - - LINK_LIBS - clangBasic - lldbBreakpoint - lldbCore - lldbDataFormatters - lldbExpression - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - LINK_COMPONENTS - Core - IRReader - Support - Target - ) diff --git a/source/Plugins/MemoryHistory/CMakeLists.txt b/source/Plugins/MemoryHistory/CMakeLists.txt deleted file mode 100644 index 113f063625789..0000000000000 --- a/source/Plugins/MemoryHistory/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(asan) diff --git a/source/Plugins/MemoryHistory/asan/CMakeLists.txt b/source/Plugins/MemoryHistory/asan/CMakeLists.txt deleted file mode 100644 index 08deb75aabb11..0000000000000 --- a/source/Plugins/MemoryHistory/asan/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginMemoryHistoryASan PLUGIN - MemoryHistoryASan.cpp - - LINK_LIBS - lldbCore - lldbExpression - lldbTarget - lldbPluginProcessUtility - ) diff --git a/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt b/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt deleted file mode 100644 index acc13d31ca257..0000000000000 --- a/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginObjectContainerBSDArchive PLUGIN - ObjectContainerBSDArchive.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ObjectContainer/CMakeLists.txt b/source/Plugins/ObjectContainer/CMakeLists.txt deleted file mode 100644 index 5dcef91f07d21..0000000000000 --- a/source/Plugins/ObjectContainer/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(BSD-Archive) -add_subdirectory(Universal-Mach-O) diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt b/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt deleted file mode 100644 index 9f173cf4c004a..0000000000000 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginObjectContainerMachOArchive PLUGIN - ObjectContainerUniversalMachO.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - ) diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp deleted file mode 100644 index 4c48d641829a4..0000000000000 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ /dev/null @@ -1,238 +0,0 @@ -//===-- ObjectContainerUniversalMachO.cpp -----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ObjectContainerUniversalMachO.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/Stream.h" - -using namespace lldb; -using namespace lldb_private; -using namespace llvm::MachO; - -void ObjectContainerUniversalMachO::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - GetModuleSpecifications); -} - -void ObjectContainerUniversalMachO::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString ObjectContainerUniversalMachO::GetPluginNameStatic() { - static ConstString g_name("mach-o"); - return g_name; -} - -const char *ObjectContainerUniversalMachO::GetPluginDescriptionStatic() { - return "Universal mach-o object container reader."; -} - -ObjectContainer *ObjectContainerUniversalMachO::CreateInstance( - const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, - lldb::offset_t data_offset, const FileSpec *file, - lldb::offset_t file_offset, lldb::offset_t length) { - // We get data when we aren't trying to look for cached container - // information, so only try and look for an architecture slice if we get data - if (data_sp) { - DataExtractor data; - data.SetData(data_sp, data_offset, length); - if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) { - std::unique_ptr<ObjectContainerUniversalMachO> container_ap( - new ObjectContainerUniversalMachO(module_sp, data_sp, data_offset, - file, file_offset, length)); - if (container_ap->ParseHeader()) { - return container_ap.release(); - } - } - } - return NULL; -} - -bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) { - lldb::offset_t offset = 0; - uint32_t magic = data.GetU32(&offset); - return magic == FAT_MAGIC || magic == FAT_CIGAM; -} - -ObjectContainerUniversalMachO::ObjectContainerUniversalMachO( - const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, - lldb::offset_t data_offset, const FileSpec *file, - lldb::offset_t file_offset, lldb::offset_t length) - : ObjectContainer(module_sp, file, file_offset, length, data_sp, - data_offset), - m_header(), m_fat_archs() { - memset(&m_header, 0, sizeof(m_header)); -} - -ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() {} - -bool ObjectContainerUniversalMachO::ParseHeader() { - bool success = ParseHeader(m_data, m_header, m_fat_archs); - // We no longer need any data, we parsed all we needed to parse and cached it - // in m_header and m_fat_archs - m_data.Clear(); - return success; -} - -bool ObjectContainerUniversalMachO::ParseHeader( - lldb_private::DataExtractor &data, llvm::MachO::fat_header &header, - std::vector<llvm::MachO::fat_arch> &fat_archs) { - bool success = false; - // Store the file offset for this universal file as we could have a universal - // .o file in a BSD archive, or be contained in another kind of object. - // Universal mach-o files always have their headers in big endian. - lldb::offset_t offset = 0; - data.SetByteOrder(eByteOrderBig); - header.magic = data.GetU32(&offset); - fat_archs.clear(); - - if (header.magic == FAT_MAGIC) { - - data.SetAddressByteSize(4); - - header.nfat_arch = data.GetU32(&offset); - - // Now we should have enough data for all of the fat headers, so lets index - // them so we know how many architectures that this universal binary - // contains. - uint32_t arch_idx = 0; - for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) { - if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) { - fat_arch arch; - if (data.GetU32(&offset, &arch, sizeof(fat_arch) / sizeof(uint32_t))) - fat_archs.push_back(arch); - } - } - success = true; - } else { - memset(&header, 0, sizeof(header)); - } - return success; -} - -void ObjectContainerUniversalMachO::Dump(Stream *s) const { - s->Printf("%p: ", static_cast<const void *>(this)); - s->Indent(); - const size_t num_archs = GetNumArchitectures(); - const size_t num_objects = GetNumObjects(); - s->Printf("ObjectContainerUniversalMachO, num_archs = %zu, num_objects = %zu", - num_archs, num_objects); - uint32_t i; - ArchSpec arch; - s->IndentMore(); - for (i = 0; i < num_archs; i++) { - s->Indent(); - GetArchitectureAtIndex(i, arch); - s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName()); - } - for (i = 0; i < num_objects; i++) { - s->Indent(); - s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex(i)); - } - s->IndentLess(); - s->EOL(); -} - -size_t ObjectContainerUniversalMachO::GetNumArchitectures() const { - return m_header.nfat_arch; -} - -bool ObjectContainerUniversalMachO::GetArchitectureAtIndex( - uint32_t idx, ArchSpec &arch) const { - if (idx < m_header.nfat_arch) { - arch.SetArchitecture(eArchTypeMachO, m_fat_archs[idx].cputype, - m_fat_archs[idx].cpusubtype); - return true; - } - return false; -} - -ObjectFileSP -ObjectContainerUniversalMachO::GetObjectFile(const FileSpec *file) { - uint32_t arch_idx = 0; - ArchSpec arch; - // If the module hasn't specified an architecture yet, set it to the default - // architecture: - ModuleSP module_sp(GetModule()); - if (module_sp) { - if (!module_sp->GetArchitecture().IsValid()) { - arch = Target::GetDefaultArchitecture(); - if (!arch.IsValid()) - arch.SetTriple(LLDB_ARCH_DEFAULT); - } else - arch = module_sp->GetArchitecture(); - - ArchSpec curr_arch; - // First, try to find an exact match for the Arch of the Target. - for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { - if (GetArchitectureAtIndex(arch_idx, curr_arch) && - arch.IsExactMatch(curr_arch)) - break; - } - - // Failing an exact match, try to find a compatible Arch of the Target. - if (arch_idx >= m_header.nfat_arch) { - for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { - if (GetArchitectureAtIndex(arch_idx, curr_arch) && - arch.IsCompatibleMatch(curr_arch)) - break; - } - } - - if (arch_idx < m_header.nfat_arch) { - DataBufferSP data_sp; - lldb::offset_t data_offset = 0; - return ObjectFile::FindPlugin( - module_sp, file, m_offset + m_fat_archs[arch_idx].offset, - m_fat_archs[arch_idx].size, data_sp, data_offset); - } - } - return ObjectFileSP(); -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString ObjectContainerUniversalMachO::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ObjectContainerUniversalMachO::GetPluginVersion() { return 1; } - -size_t ObjectContainerUniversalMachO::GetModuleSpecifications( - const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, lldb::offset_t file_offset, - lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { - const size_t initial_count = specs.GetSize(); - - DataExtractor data; - data.SetData(data_sp, data_offset, data_sp->GetByteSize()); - - if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) { - llvm::MachO::fat_header header; - std::vector<llvm::MachO::fat_arch> fat_archs; - if (ParseHeader(data, header, fat_archs)) { - for (const llvm::MachO::fat_arch &fat_arch : fat_archs) { - const lldb::offset_t slice_file_offset = fat_arch.offset + file_offset; - if (fat_arch.offset < file_size && file_size > slice_file_offset) { - ObjectFile::GetModuleSpecifications( - file, slice_file_offset, file_size - slice_file_offset, specs); - } - } - } - } - return specs.GetSize() - initial_count; -} diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h deleted file mode 100644 index d6e4fe1747cfb..0000000000000 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h +++ /dev/null @@ -1,82 +0,0 @@ -//===-- ObjectContainerUniversalMachO.h -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ObjectContainerUniversalMachO_h_ -#define liblldb_ObjectContainerUniversalMachO_h_ - -#include "lldb/Host/SafeMachO.h" -#include "lldb/Symbol/ObjectContainer.h" -#include "lldb/Utility/FileSpec.h" - -class ObjectContainerUniversalMachO : public lldb_private::ObjectContainer { -public: - ObjectContainerUniversalMachO(const lldb::ModuleSP &module_sp, - lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - const lldb_private::FileSpec *file, - lldb::offset_t offset, lldb::offset_t length); - - ~ObjectContainerUniversalMachO() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::ObjectContainer * - CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, const lldb_private::FileSpec *file, - lldb::offset_t offset, lldb::offset_t length); - - static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, - lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - lldb::offset_t file_offset, - lldb::offset_t length, - lldb_private::ModuleSpecList &specs); - - static bool MagicBytesMatch(const lldb_private::DataExtractor &data); - - //------------------------------------------------------------------ - // Member Functions - //------------------------------------------------------------------ - bool ParseHeader() override; - - void Dump(lldb_private::Stream *s) const override; - - size_t GetNumArchitectures() const override; - - bool GetArchitectureAtIndex(uint32_t cpu_idx, - lldb_private::ArchSpec &arch) const override; - - lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - llvm::MachO::fat_header m_header; - std::vector<llvm::MachO::fat_arch> m_fat_archs; - - static bool ParseHeader(lldb_private::DataExtractor &data, - llvm::MachO::fat_header &header, - std::vector<llvm::MachO::fat_arch> &fat_archs); -}; - -#endif // liblldb_ObjectContainerUniversalMachO_h_ diff --git a/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt b/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt deleted file mode 100644 index 2f51b2c8719a7..0000000000000 --- a/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginObjectFileBreakpad PLUGIN - ObjectFileBreakpad.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ObjectFile/CMakeLists.txt b/source/Plugins/ObjectFile/CMakeLists.txt deleted file mode 100644 index 4edd667b9723d..0000000000000 --- a/source/Plugins/ObjectFile/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory(Breakpad) -add_subdirectory(ELF) -add_subdirectory(Mach-O) -add_subdirectory(PECOFF) -add_subdirectory(JIT) diff --git a/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/source/Plugins/ObjectFile/ELF/CMakeLists.txt deleted file mode 100644 index 45a4edcbb1c9e..0000000000000 --- a/source/Plugins/ObjectFile/ELF/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_lldb_library(lldbPluginObjectFileELF PLUGIN - ELFHeader.cpp - ObjectFileELF.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - LINK_COMPONENTS - BinaryFormat - Object - Support - ) diff --git a/source/Plugins/ObjectFile/JIT/CMakeLists.txt b/source/Plugins/ObjectFile/JIT/CMakeLists.txt deleted file mode 100644 index fd575532db4c7..0000000000000 --- a/source/Plugins/ObjectFile/JIT/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginObjectFileJIT PLUGIN - ObjectFileJIT.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt b/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt deleted file mode 100644 index d39b93768ae7d..0000000000000 --- a/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginObjectFileMachO PLUGIN - ObjectFileMachO.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp deleted file mode 100644 index 06908fecf9841..0000000000000 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ /dev/null @@ -1,6380 +0,0 @@ -//===-- ObjectFileMachO.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/StringRef.h" - -#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h" -#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h" -#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" -#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/RangeMap.h" -#include "lldb/Core/Section.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Host/Host.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/SectionLoadList.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadList.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timer.h" -#include "lldb/Utility/UUID.h" - -#include "lldb/Host/SafeMachO.h" - -#include "llvm/Support/MemoryBuffer.h" - -#include "ObjectFileMachO.h" - -#if defined(__APPLE__) && \ - (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) -// GetLLDBSharedCacheUUID() needs to call dlsym() -#include <dlfcn.h> -#endif - -#ifndef __APPLE__ -#include "Utility/UuidCompatibility.h" -#else -#include <uuid/uuid.h> -#endif - -#define THUMB_ADDRESS_BIT_MASK 0xfffffffffffffffeull -using namespace lldb; -using namespace lldb_private; -using namespace llvm::MachO; - -// Some structure definitions needed for parsing the dyld shared cache files -// found on iOS devices. - -struct lldb_copy_dyld_cache_header_v1 { - char magic[16]; // e.g. "dyld_v0 i386", "dyld_v1 armv7", etc. - uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info - uint32_t mappingCount; // number of dyld_cache_mapping_info entries - uint32_t imagesOffset; - uint32_t imagesCount; - uint64_t dyldBaseAddress; - uint64_t codeSignatureOffset; - uint64_t codeSignatureSize; - uint64_t slideInfoOffset; - uint64_t slideInfoSize; - uint64_t localSymbolsOffset; - uint64_t localSymbolsSize; - uint8_t uuid[16]; // v1 and above, also recorded in dyld_all_image_infos v13 - // and later -}; - -struct lldb_copy_dyld_cache_mapping_info { - uint64_t address; - uint64_t size; - uint64_t fileOffset; - uint32_t maxProt; - uint32_t initProt; -}; - -struct lldb_copy_dyld_cache_local_symbols_info { - uint32_t nlistOffset; - uint32_t nlistCount; - uint32_t stringsOffset; - uint32_t stringsSize; - uint32_t entriesOffset; - uint32_t entriesCount; -}; -struct lldb_copy_dyld_cache_local_symbols_entry { - uint32_t dylibOffset; - uint32_t nlistStartIndex; - uint32_t nlistCount; -}; - -class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 { -public: - RegisterContextDarwin_x86_64_Mach(lldb_private::Thread &thread, - const DataExtractor &data) - : RegisterContextDarwin_x86_64(thread, 0) { - SetRegisterDataFrom_LC_THREAD(data); - } - - void InvalidateAllRegisters() override { - // Do nothing... registers are always valid... - } - - void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) { - lldb::offset_t offset = 0; - SetError(GPRRegSet, Read, -1); - SetError(FPURegSet, Read, -1); - SetError(EXCRegSet, Read, -1); - bool done = false; - - while (!done) { - int flavor = data.GetU32(&offset); - if (flavor == 0) - done = true; - else { - uint32_t i; - uint32_t count = data.GetU32(&offset); - switch (flavor) { - case GPRRegSet: - for (i = 0; i < count; ++i) - (&gpr.rax)[i] = data.GetU64(&offset); - SetError(GPRRegSet, Read, 0); - done = true; - - break; - case FPURegSet: - // TODO: fill in FPU regs.... - // SetError (FPURegSet, Read, -1); - done = true; - - break; - case EXCRegSet: - exc.trapno = data.GetU32(&offset); - exc.err = data.GetU32(&offset); - exc.faultvaddr = data.GetU64(&offset); - SetError(EXCRegSet, Read, 0); - done = true; - break; - case 7: - case 8: - case 9: - // fancy flavors that encapsulate of the above flavors... - break; - - default: - done = true; - break; - } - } - } - } - - static size_t WriteRegister(RegisterContext *reg_ctx, const char *name, - const char *alt_name, size_t reg_byte_size, - Stream &data) { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) - reg_info = reg_ctx->GetRegisterInfoByName(alt_name); - if (reg_info) { - lldb_private::RegisterValue reg_value; - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - if (reg_info->byte_size >= reg_byte_size) - data.Write(reg_value.GetBytes(), reg_byte_size); - else { - data.Write(reg_value.GetBytes(), reg_info->byte_size); - for (size_t i = 0, n = reg_byte_size - reg_info->byte_size; i < n; - ++i) - data.PutChar(0); - } - return reg_byte_size; - } - } - // Just write zeros if all else fails - for (size_t i = 0; i < reg_byte_size; ++i) - data.PutChar(0); - return reg_byte_size; - } - - static bool Create_LC_THREAD(Thread *thread, Stream &data) { - RegisterContextSP reg_ctx_sp(thread->GetRegisterContext()); - if (reg_ctx_sp) { - RegisterContext *reg_ctx = reg_ctx_sp.get(); - - data.PutHex32(GPRRegSet); // Flavor - data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "rax", NULL, 8, data); - WriteRegister(reg_ctx, "rbx", NULL, 8, data); - WriteRegister(reg_ctx, "rcx", NULL, 8, data); - WriteRegister(reg_ctx, "rdx", NULL, 8, data); - WriteRegister(reg_ctx, "rdi", NULL, 8, data); - WriteRegister(reg_ctx, "rsi", NULL, 8, data); - WriteRegister(reg_ctx, "rbp", NULL, 8, data); - WriteRegister(reg_ctx, "rsp", NULL, 8, data); - WriteRegister(reg_ctx, "r8", NULL, 8, data); - WriteRegister(reg_ctx, "r9", NULL, 8, data); - WriteRegister(reg_ctx, "r10", NULL, 8, data); - WriteRegister(reg_ctx, "r11", NULL, 8, data); - WriteRegister(reg_ctx, "r12", NULL, 8, data); - WriteRegister(reg_ctx, "r13", NULL, 8, data); - WriteRegister(reg_ctx, "r14", NULL, 8, data); - WriteRegister(reg_ctx, "r15", NULL, 8, data); - WriteRegister(reg_ctx, "rip", NULL, 8, data); - WriteRegister(reg_ctx, "rflags", NULL, 8, data); - WriteRegister(reg_ctx, "cs", NULL, 8, data); - WriteRegister(reg_ctx, "fs", NULL, 8, data); - WriteRegister(reg_ctx, "gs", NULL, 8, data); - - // // Write out the FPU registers - // const size_t fpu_byte_size = sizeof(FPU); - // size_t bytes_written = 0; - // data.PutHex32 (FPURegSet); - // data.PutHex32 (fpu_byte_size/sizeof(uint64_t)); - // bytes_written += data.PutHex32(0); // uint32_t pad[0] - // bytes_written += data.PutHex32(0); // uint32_t pad[1] - // bytes_written += WriteRegister (reg_ctx, "fcw", "fctrl", 2, - // data); // uint16_t fcw; // "fctrl" - // bytes_written += WriteRegister (reg_ctx, "fsw" , "fstat", 2, - // data); // uint16_t fsw; // "fstat" - // bytes_written += WriteRegister (reg_ctx, "ftw" , "ftag", 1, - // data); // uint8_t ftw; // "ftag" - // bytes_written += data.PutHex8 (0); // uint8_t pad1; - // bytes_written += WriteRegister (reg_ctx, "fop" , NULL, 2, - // data); // uint16_t fop; // "fop" - // bytes_written += WriteRegister (reg_ctx, "fioff", "ip", 4, - // data); // uint32_t ip; // "fioff" - // bytes_written += WriteRegister (reg_ctx, "fiseg", NULL, 2, - // data); // uint16_t cs; // "fiseg" - // bytes_written += data.PutHex16 (0); // uint16_t pad2; - // bytes_written += WriteRegister (reg_ctx, "dp", "fooff" , 4, - // data); // uint32_t dp; // "fooff" - // bytes_written += WriteRegister (reg_ctx, "foseg", NULL, 2, - // data); // uint16_t ds; // "foseg" - // bytes_written += data.PutHex16 (0); // uint16_t pad3; - // bytes_written += WriteRegister (reg_ctx, "mxcsr", NULL, 4, - // data); // uint32_t mxcsr; - // bytes_written += WriteRegister (reg_ctx, "mxcsrmask", NULL, - // 4, data);// uint32_t mxcsrmask; - // bytes_written += WriteRegister (reg_ctx, "stmm0", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm1", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm2", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm3", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm4", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm5", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm6", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "stmm7", NULL, - // sizeof(MMSReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm0" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm1" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm2" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm3" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm4" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm5" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm6" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm7" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm8" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm9" , NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm10", NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm11", NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm12", NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm13", NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm14", NULL, - // sizeof(XMMReg), data); - // bytes_written += WriteRegister (reg_ctx, "xmm15", NULL, - // sizeof(XMMReg), data); - // - // // Fill rest with zeros - // for (size_t i=0, n = fpu_byte_size - bytes_written; i<n; ++ - // i) - // data.PutChar(0); - - // Write out the EXC registers - data.PutHex32(EXCRegSet); - data.PutHex32(EXCWordCount); - WriteRegister(reg_ctx, "trapno", NULL, 4, data); - WriteRegister(reg_ctx, "err", NULL, 4, data); - WriteRegister(reg_ctx, "faultvaddr", NULL, 8, data); - return true; - } - return false; - } - -protected: - int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return 0; } - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return 0; } - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return 0; } - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override { - return 0; - } - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override { - return 0; - } - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override { - return 0; - } -}; - -class RegisterContextDarwin_i386_Mach : public RegisterContextDarwin_i386 { -public: - RegisterContextDarwin_i386_Mach(lldb_private::Thread &thread, - const DataExtractor &data) - : RegisterContextDarwin_i386(thread, 0) { - SetRegisterDataFrom_LC_THREAD(data); - } - - void InvalidateAllRegisters() override { - // Do nothing... registers are always valid... - } - - void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) { - lldb::offset_t offset = 0; - SetError(GPRRegSet, Read, -1); - SetError(FPURegSet, Read, -1); - SetError(EXCRegSet, Read, -1); - bool done = false; - - while (!done) { - int flavor = data.GetU32(&offset); - if (flavor == 0) - done = true; - else { - uint32_t i; - uint32_t count = data.GetU32(&offset); - switch (flavor) { - case GPRRegSet: - for (i = 0; i < count; ++i) - (&gpr.eax)[i] = data.GetU32(&offset); - SetError(GPRRegSet, Read, 0); - done = true; - - break; - case FPURegSet: - // TODO: fill in FPU regs.... - // SetError (FPURegSet, Read, -1); - done = true; - - break; - case EXCRegSet: - exc.trapno = data.GetU32(&offset); - exc.err = data.GetU32(&offset); - exc.faultvaddr = data.GetU32(&offset); - SetError(EXCRegSet, Read, 0); - done = true; - break; - case 7: - case 8: - case 9: - // fancy flavors that encapsulate of the above flavors... - break; - - default: - done = true; - break; - } - } - } - } - - static size_t WriteRegister(RegisterContext *reg_ctx, const char *name, - const char *alt_name, size_t reg_byte_size, - Stream &data) { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) - reg_info = reg_ctx->GetRegisterInfoByName(alt_name); - if (reg_info) { - lldb_private::RegisterValue reg_value; - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - if (reg_info->byte_size >= reg_byte_size) - data.Write(reg_value.GetBytes(), reg_byte_size); - else { - data.Write(reg_value.GetBytes(), reg_info->byte_size); - for (size_t i = 0, n = reg_byte_size - reg_info->byte_size; i < n; - ++i) - data.PutChar(0); - } - return reg_byte_size; - } - } - // Just write zeros if all else fails - for (size_t i = 0; i < reg_byte_size; ++i) - data.PutChar(0); - return reg_byte_size; - } - - static bool Create_LC_THREAD(Thread *thread, Stream &data) { - RegisterContextSP reg_ctx_sp(thread->GetRegisterContext()); - if (reg_ctx_sp) { - RegisterContext *reg_ctx = reg_ctx_sp.get(); - - data.PutHex32(GPRRegSet); // Flavor - data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "eax", NULL, 4, data); - WriteRegister(reg_ctx, "ebx", NULL, 4, data); - WriteRegister(reg_ctx, "ecx", NULL, 4, data); - WriteRegister(reg_ctx, "edx", NULL, 4, data); - WriteRegister(reg_ctx, "edi", NULL, 4, data); - WriteRegister(reg_ctx, "esi", NULL, 4, data); - WriteRegister(reg_ctx, "ebp", NULL, 4, data); - WriteRegister(reg_ctx, "esp", NULL, 4, data); - WriteRegister(reg_ctx, "ss", NULL, 4, data); - WriteRegister(reg_ctx, "eflags", NULL, 4, data); - WriteRegister(reg_ctx, "eip", NULL, 4, data); - WriteRegister(reg_ctx, "cs", NULL, 4, data); - WriteRegister(reg_ctx, "ds", NULL, 4, data); - WriteRegister(reg_ctx, "es", NULL, 4, data); - WriteRegister(reg_ctx, "fs", NULL, 4, data); - WriteRegister(reg_ctx, "gs", NULL, 4, data); - - // Write out the EXC registers - data.PutHex32(EXCRegSet); - data.PutHex32(EXCWordCount); - WriteRegister(reg_ctx, "trapno", NULL, 4, data); - WriteRegister(reg_ctx, "err", NULL, 4, data); - WriteRegister(reg_ctx, "faultvaddr", NULL, 4, data); - return true; - } - return false; - } - -protected: - int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return 0; } - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return 0; } - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return 0; } - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override { - return 0; - } - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override { - return 0; - } - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override { - return 0; - } -}; - -class RegisterContextDarwin_arm_Mach : public RegisterContextDarwin_arm { -public: - RegisterContextDarwin_arm_Mach(lldb_private::Thread &thread, - const DataExtractor &data) - : RegisterContextDarwin_arm(thread, 0) { - SetRegisterDataFrom_LC_THREAD(data); - } - - void InvalidateAllRegisters() override { - // Do nothing... registers are always valid... - } - - void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) { - lldb::offset_t offset = 0; - SetError(GPRRegSet, Read, -1); - SetError(FPURegSet, Read, -1); - SetError(EXCRegSet, Read, -1); - bool done = false; - - while (!done) { - int flavor = data.GetU32(&offset); - uint32_t count = data.GetU32(&offset); - lldb::offset_t next_thread_state = offset + (count * 4); - switch (flavor) { - case GPRAltRegSet: - case GPRRegSet: - for (uint32_t i = 0; i < count; ++i) { - gpr.r[i] = data.GetU32(&offset); - } - - // Note that gpr.cpsr is also copied by the above loop; this loop - // technically extends one element past the end of the gpr.r[] array. - - SetError(GPRRegSet, Read, 0); - offset = next_thread_state; - break; - - case FPURegSet: { - uint8_t *fpu_reg_buf = (uint8_t *)&fpu.floats.s[0]; - const int fpu_reg_buf_size = sizeof(fpu.floats); - if (data.ExtractBytes(offset, fpu_reg_buf_size, eByteOrderLittle, - fpu_reg_buf) == fpu_reg_buf_size) { - offset += fpu_reg_buf_size; - fpu.fpscr = data.GetU32(&offset); - SetError(FPURegSet, Read, 0); - } else { - done = true; - } - } - offset = next_thread_state; - break; - - case EXCRegSet: - if (count == 3) { - exc.exception = data.GetU32(&offset); - exc.fsr = data.GetU32(&offset); - exc.far = data.GetU32(&offset); - SetError(EXCRegSet, Read, 0); - } - done = true; - offset = next_thread_state; - break; - - // Unknown register set flavor, stop trying to parse. - default: - done = true; - } - } - } - - static size_t WriteRegister(RegisterContext *reg_ctx, const char *name, - const char *alt_name, size_t reg_byte_size, - Stream &data) { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) - reg_info = reg_ctx->GetRegisterInfoByName(alt_name); - if (reg_info) { - lldb_private::RegisterValue reg_value; - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - if (reg_info->byte_size >= reg_byte_size) - data.Write(reg_value.GetBytes(), reg_byte_size); - else { - data.Write(reg_value.GetBytes(), reg_info->byte_size); - for (size_t i = 0, n = reg_byte_size - reg_info->byte_size; i < n; - ++i) - data.PutChar(0); - } - return reg_byte_size; - } - } - // Just write zeros if all else fails - for (size_t i = 0; i < reg_byte_size; ++i) - data.PutChar(0); - return reg_byte_size; - } - - static bool Create_LC_THREAD(Thread *thread, Stream &data) { - RegisterContextSP reg_ctx_sp(thread->GetRegisterContext()); - if (reg_ctx_sp) { - RegisterContext *reg_ctx = reg_ctx_sp.get(); - - data.PutHex32(GPRRegSet); // Flavor - data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "r0", NULL, 4, data); - WriteRegister(reg_ctx, "r1", NULL, 4, data); - WriteRegister(reg_ctx, "r2", NULL, 4, data); - WriteRegister(reg_ctx, "r3", NULL, 4, data); - WriteRegister(reg_ctx, "r4", NULL, 4, data); - WriteRegister(reg_ctx, "r5", NULL, 4, data); - WriteRegister(reg_ctx, "r6", NULL, 4, data); - WriteRegister(reg_ctx, "r7", NULL, 4, data); - WriteRegister(reg_ctx, "r8", NULL, 4, data); - WriteRegister(reg_ctx, "r9", NULL, 4, data); - WriteRegister(reg_ctx, "r10", NULL, 4, data); - WriteRegister(reg_ctx, "r11", NULL, 4, data); - WriteRegister(reg_ctx, "r12", NULL, 4, data); - WriteRegister(reg_ctx, "sp", NULL, 4, data); - WriteRegister(reg_ctx, "lr", NULL, 4, data); - WriteRegister(reg_ctx, "pc", NULL, 4, data); - WriteRegister(reg_ctx, "cpsr", NULL, 4, data); - - // Write out the EXC registers - // data.PutHex32 (EXCRegSet); - // data.PutHex32 (EXCWordCount); - // WriteRegister (reg_ctx, "exception", NULL, 4, data); - // WriteRegister (reg_ctx, "fsr", NULL, 4, data); - // WriteRegister (reg_ctx, "far", NULL, 4, data); - return true; - } - return false; - } - -protected: - int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; } - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; } - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; } - - int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) override { return -1; } - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override { - return 0; - } - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override { - return 0; - } - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override { - return 0; - } - - int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) override { - return -1; - } -}; - -class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 { -public: - RegisterContextDarwin_arm64_Mach(lldb_private::Thread &thread, - const DataExtractor &data) - : RegisterContextDarwin_arm64(thread, 0) { - SetRegisterDataFrom_LC_THREAD(data); - } - - void InvalidateAllRegisters() override { - // Do nothing... registers are always valid... - } - - void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) { - lldb::offset_t offset = 0; - SetError(GPRRegSet, Read, -1); - SetError(FPURegSet, Read, -1); - SetError(EXCRegSet, Read, -1); - bool done = false; - while (!done) { - int flavor = data.GetU32(&offset); - uint32_t count = data.GetU32(&offset); - lldb::offset_t next_thread_state = offset + (count * 4); - switch (flavor) { - case GPRRegSet: - // x0-x29 + fp + lr + sp + pc (== 33 64-bit registers) plus cpsr (1 - // 32-bit register) - if (count >= (33 * 2) + 1) { - for (uint32_t i = 0; i < 29; ++i) - gpr.x[i] = data.GetU64(&offset); - gpr.fp = data.GetU64(&offset); - gpr.lr = data.GetU64(&offset); - gpr.sp = data.GetU64(&offset); - gpr.pc = data.GetU64(&offset); - gpr.cpsr = data.GetU32(&offset); - SetError(GPRRegSet, Read, 0); - } - offset = next_thread_state; - break; - case FPURegSet: { - uint8_t *fpu_reg_buf = (uint8_t *)&fpu.v[0]; - const int fpu_reg_buf_size = sizeof(fpu); - if (fpu_reg_buf_size == count * sizeof(uint32_t) && - data.ExtractBytes(offset, fpu_reg_buf_size, eByteOrderLittle, - fpu_reg_buf) == fpu_reg_buf_size) { - SetError(FPURegSet, Read, 0); - } else { - done = true; - } - } - offset = next_thread_state; - break; - case EXCRegSet: - if (count == 4) { - exc.far = data.GetU64(&offset); - exc.esr = data.GetU32(&offset); - exc.exception = data.GetU32(&offset); - SetError(EXCRegSet, Read, 0); - } - offset = next_thread_state; - break; - default: - done = true; - break; - } - } - } - - static size_t WriteRegister(RegisterContext *reg_ctx, const char *name, - const char *alt_name, size_t reg_byte_size, - Stream &data) { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name); - if (reg_info == NULL) - reg_info = reg_ctx->GetRegisterInfoByName(alt_name); - if (reg_info) { - lldb_private::RegisterValue reg_value; - if (reg_ctx->ReadRegister(reg_info, reg_value)) { - if (reg_info->byte_size >= reg_byte_size) - data.Write(reg_value.GetBytes(), reg_byte_size); - else { - data.Write(reg_value.GetBytes(), reg_info->byte_size); - for (size_t i = 0, n = reg_byte_size - reg_info->byte_size; i < n; - ++i) - data.PutChar(0); - } - return reg_byte_size; - } - } - // Just write zeros if all else fails - for (size_t i = 0; i < reg_byte_size; ++i) - data.PutChar(0); - return reg_byte_size; - } - - static bool Create_LC_THREAD(Thread *thread, Stream &data) { - RegisterContextSP reg_ctx_sp(thread->GetRegisterContext()); - if (reg_ctx_sp) { - RegisterContext *reg_ctx = reg_ctx_sp.get(); - - data.PutHex32(GPRRegSet); // Flavor - data.PutHex32(GPRWordCount); - WriteRegister(reg_ctx, "x0", NULL, 8, data); - WriteRegister(reg_ctx, "x1", NULL, 8, data); - WriteRegister(reg_ctx, "x2", NULL, 8, data); - WriteRegister(reg_ctx, "x3", NULL, 8, data); - WriteRegister(reg_ctx, "x4", NULL, 8, data); - WriteRegister(reg_ctx, "x5", NULL, 8, data); - WriteRegister(reg_ctx, "x6", NULL, 8, data); - WriteRegister(reg_ctx, "x7", NULL, 8, data); - WriteRegister(reg_ctx, "x8", NULL, 8, data); - WriteRegister(reg_ctx, "x9", NULL, 8, data); - WriteRegister(reg_ctx, "x10", NULL, 8, data); - WriteRegister(reg_ctx, "x11", NULL, 8, data); - WriteRegister(reg_ctx, "x12", NULL, 8, data); - WriteRegister(reg_ctx, "x13", NULL, 8, data); - WriteRegister(reg_ctx, "x14", NULL, 8, data); - WriteRegister(reg_ctx, "x15", NULL, 8, data); - WriteRegister(reg_ctx, "x16", NULL, 8, data); - WriteRegister(reg_ctx, "x17", NULL, 8, data); - WriteRegister(reg_ctx, "x18", NULL, 8, data); - WriteRegister(reg_ctx, "x19", NULL, 8, data); - WriteRegister(reg_ctx, "x20", NULL, 8, data); - WriteRegister(reg_ctx, "x21", NULL, 8, data); - WriteRegister(reg_ctx, "x22", NULL, 8, data); - WriteRegister(reg_ctx, "x23", NULL, 8, data); - WriteRegister(reg_ctx, "x24", NULL, 8, data); - WriteRegister(reg_ctx, "x25", NULL, 8, data); - WriteRegister(reg_ctx, "x26", NULL, 8, data); - WriteRegister(reg_ctx, "x27", NULL, 8, data); - WriteRegister(reg_ctx, "x28", NULL, 8, data); - WriteRegister(reg_ctx, "fp", NULL, 8, data); - WriteRegister(reg_ctx, "lr", NULL, 8, data); - WriteRegister(reg_ctx, "sp", NULL, 8, data); - WriteRegister(reg_ctx, "pc", NULL, 8, data); - WriteRegister(reg_ctx, "cpsr", NULL, 4, data); - - // Write out the EXC registers - // data.PutHex32 (EXCRegSet); - // data.PutHex32 (EXCWordCount); - // WriteRegister (reg_ctx, "far", NULL, 8, data); - // WriteRegister (reg_ctx, "esr", NULL, 4, data); - // WriteRegister (reg_ctx, "exception", NULL, 4, data); - return true; - } - return false; - } - -protected: - int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; } - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; } - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; } - - int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) override { return -1; } - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override { - return 0; - } - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override { - return 0; - } - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override { - return 0; - } - - int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) override { - return -1; - } -}; - -static uint32_t MachHeaderSizeFromMagic(uint32_t magic) { - switch (magic) { - case MH_MAGIC: - case MH_CIGAM: - return sizeof(struct mach_header); - - case MH_MAGIC_64: - case MH_CIGAM_64: - return sizeof(struct mach_header_64); - break; - - default: - break; - } - return 0; -} - -#define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008 - -void ObjectFileMachO::Initialize() { - PluginManager::RegisterPlugin( - GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance, GetModuleSpecifications, SaveCore); -} - -void ObjectFileMachO::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString ObjectFileMachO::GetPluginNameStatic() { - static ConstString g_name("mach-o"); - return g_name; -} - -const char *ObjectFileMachO::GetPluginDescriptionStatic() { - return "Mach-o object file reader (32 and 64 bit)"; -} - -ObjectFile *ObjectFileMachO::CreateInstance(const lldb::ModuleSP &module_sp, - DataBufferSP &data_sp, - lldb::offset_t data_offset, - const FileSpec *file, - lldb::offset_t file_offset, - lldb::offset_t length) { - if (!data_sp) { - data_sp = MapFileData(*file, length, file_offset); - if (!data_sp) - return nullptr; - data_offset = 0; - } - - if (!ObjectFileMachO::MagicBytesMatch(data_sp, data_offset, length)) - return nullptr; - - // Update the data to contain the entire file if it doesn't already - if (data_sp->GetByteSize() < length) { - data_sp = MapFileData(*file, length, file_offset); - if (!data_sp) - return nullptr; - data_offset = 0; - } - auto objfile_ap = llvm::make_unique<ObjectFileMachO>( - module_sp, data_sp, data_offset, file, file_offset, length); - if (!objfile_ap || !objfile_ap->ParseHeader()) - return nullptr; - - return objfile_ap.release(); -} - -ObjectFile *ObjectFileMachO::CreateMemoryInstance( - const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, - const ProcessSP &process_sp, lldb::addr_t header_addr) { - if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) { - std::unique_ptr<ObjectFile> objfile_ap( - new ObjectFileMachO(module_sp, data_sp, process_sp, header_addr)); - if (objfile_ap.get() && objfile_ap->ParseHeader()) - return objfile_ap.release(); - } - return NULL; -} - -size_t ObjectFileMachO::GetModuleSpecifications( - const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, lldb::offset_t file_offset, - lldb::offset_t length, lldb_private::ModuleSpecList &specs) { - const size_t initial_count = specs.GetSize(); - - if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) { - DataExtractor data; - data.SetData(data_sp); - llvm::MachO::mach_header header; - if (ParseHeader(data, &data_offset, header)) { - size_t header_and_load_cmds = - header.sizeofcmds + MachHeaderSizeFromMagic(header.magic); - if (header_and_load_cmds >= data_sp->GetByteSize()) { - data_sp = MapFileData(file, header_and_load_cmds, file_offset); - data.SetData(data_sp); - data_offset = MachHeaderSizeFromMagic(header.magic); - } - if (data_sp) { - ModuleSpec spec; - spec.GetFileSpec() = file; - spec.SetObjectOffset(file_offset); - spec.SetObjectSize(length); - - spec.GetArchitecture() = GetArchitecture(header, data, data_offset); - if (spec.GetArchitecture().IsValid()) { - GetUUID(header, data, data_offset, spec.GetUUID()); - specs.Append(spec); - } - } - } - } - return specs.GetSize() - initial_count; -} - -const ConstString &ObjectFileMachO::GetSegmentNameTEXT() { - static ConstString g_segment_name_TEXT("__TEXT"); - return g_segment_name_TEXT; -} - -const ConstString &ObjectFileMachO::GetSegmentNameDATA() { - static ConstString g_segment_name_DATA("__DATA"); - return g_segment_name_DATA; -} - -const ConstString &ObjectFileMachO::GetSegmentNameDATA_DIRTY() { - static ConstString g_segment_name("__DATA_DIRTY"); - return g_segment_name; -} - -const ConstString &ObjectFileMachO::GetSegmentNameDATA_CONST() { - static ConstString g_segment_name("__DATA_CONST"); - return g_segment_name; -} - -const ConstString &ObjectFileMachO::GetSegmentNameOBJC() { - static ConstString g_segment_name_OBJC("__OBJC"); - return g_segment_name_OBJC; -} - -const ConstString &ObjectFileMachO::GetSegmentNameLINKEDIT() { - static ConstString g_section_name_LINKEDIT("__LINKEDIT"); - return g_section_name_LINKEDIT; -} - -const ConstString &ObjectFileMachO::GetSegmentNameDWARF() { - static ConstString g_section_name("__DWARF"); - return g_section_name; -} - -const ConstString &ObjectFileMachO::GetSectionNameEHFrame() { - static ConstString g_section_name_eh_frame("__eh_frame"); - return g_section_name_eh_frame; -} - -bool ObjectFileMachO::MagicBytesMatch(DataBufferSP &data_sp, - lldb::addr_t data_offset, - lldb::addr_t data_length) { - DataExtractor data; - data.SetData(data_sp, data_offset, data_length); - lldb::offset_t offset = 0; - uint32_t magic = data.GetU32(&offset); - return MachHeaderSizeFromMagic(magic) != 0; -} - -ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, - DataBufferSP &data_sp, - lldb::offset_t data_offset, - const FileSpec *file, - lldb::offset_t file_offset, - lldb::offset_t length) - : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), - m_mach_segments(), m_mach_sections(), m_entry_point_address(), - m_thread_context_offsets(), m_thread_context_offsets_valid(false), - m_reexported_dylibs(), m_allow_assembly_emulation_unwind_plans(true) { - ::memset(&m_header, 0, sizeof(m_header)); - ::memset(&m_dysymtab, 0, sizeof(m_dysymtab)); -} - -ObjectFileMachO::ObjectFileMachO(const lldb::ModuleSP &module_sp, - lldb::DataBufferSP &header_data_sp, - const lldb::ProcessSP &process_sp, - lldb::addr_t header_addr) - : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), - m_mach_segments(), m_mach_sections(), m_entry_point_address(), - m_thread_context_offsets(), m_thread_context_offsets_valid(false), - m_reexported_dylibs(), m_allow_assembly_emulation_unwind_plans(true) { - ::memset(&m_header, 0, sizeof(m_header)); - ::memset(&m_dysymtab, 0, sizeof(m_dysymtab)); -} - -bool ObjectFileMachO::ParseHeader(DataExtractor &data, - lldb::offset_t *data_offset_ptr, - llvm::MachO::mach_header &header) { - data.SetByteOrder(endian::InlHostByteOrder()); - // Leave magic in the original byte order - header.magic = data.GetU32(data_offset_ptr); - bool can_parse = false; - bool is_64_bit = false; - switch (header.magic) { - case MH_MAGIC: - data.SetByteOrder(endian::InlHostByteOrder()); - data.SetAddressByteSize(4); - can_parse = true; - break; - - case MH_MAGIC_64: - data.SetByteOrder(endian::InlHostByteOrder()); - data.SetAddressByteSize(8); - can_parse = true; - is_64_bit = true; - break; - - case MH_CIGAM: - data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig - ? eByteOrderLittle - : eByteOrderBig); - data.SetAddressByteSize(4); - can_parse = true; - break; - - case MH_CIGAM_64: - data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig - ? eByteOrderLittle - : eByteOrderBig); - data.SetAddressByteSize(8); - is_64_bit = true; - can_parse = true; - break; - - default: - break; - } - - if (can_parse) { - data.GetU32(data_offset_ptr, &header.cputype, 6); - if (is_64_bit) - *data_offset_ptr += 4; - return true; - } else { - memset(&header, 0, sizeof(header)); - } - return false; -} - -bool ObjectFileMachO::ParseHeader() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - bool can_parse = false; - lldb::offset_t offset = 0; - m_data.SetByteOrder(endian::InlHostByteOrder()); - // Leave magic in the original byte order - m_header.magic = m_data.GetU32(&offset); - switch (m_header.magic) { - case MH_MAGIC: - m_data.SetByteOrder(endian::InlHostByteOrder()); - m_data.SetAddressByteSize(4); - can_parse = true; - break; - - case MH_MAGIC_64: - m_data.SetByteOrder(endian::InlHostByteOrder()); - m_data.SetAddressByteSize(8); - can_parse = true; - break; - - case MH_CIGAM: - m_data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig - ? eByteOrderLittle - : eByteOrderBig); - m_data.SetAddressByteSize(4); - can_parse = true; - break; - - case MH_CIGAM_64: - m_data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig - ? eByteOrderLittle - : eByteOrderBig); - m_data.SetAddressByteSize(8); - can_parse = true; - break; - - default: - break; - } - - if (can_parse) { - m_data.GetU32(&offset, &m_header.cputype, 6); - - if (ArchSpec mach_arch = GetArchitecture()) { - // Check if the module has a required architecture - const ArchSpec &module_arch = module_sp->GetArchitecture(); - if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch)) - return false; - - if (SetModulesArchitecture(mach_arch)) { - const size_t header_and_lc_size = - m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic); - if (m_data.GetByteSize() < header_and_lc_size) { - DataBufferSP data_sp; - ProcessSP process_sp(m_process_wp.lock()); - if (process_sp) { - data_sp = - ReadMemory(process_sp, m_memory_addr, header_and_lc_size); - } else { - // Read in all only the load command data from the file on disk - data_sp = MapFileData(m_file, header_and_lc_size, m_file_offset); - if (data_sp->GetByteSize() != header_and_lc_size) - return false; - } - if (data_sp) - m_data.SetData(data_sp); - } - } - return true; - } - } else { - memset(&m_header, 0, sizeof(struct mach_header)); - } - } - return false; -} - -ByteOrder ObjectFileMachO::GetByteOrder() const { - return m_data.GetByteOrder(); -} - -bool ObjectFileMachO::IsExecutable() const { - return m_header.filetype == MH_EXECUTE; -} - -uint32_t ObjectFileMachO::GetAddressByteSize() const { - return m_data.GetAddressByteSize(); -} - -AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) { - Symtab *symtab = GetSymtab(); - if (symtab) { - Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); - if (symbol) { - if (symbol->ValueIsAddress()) { - SectionSP section_sp(symbol->GetAddressRef().GetSection()); - if (section_sp) { - const lldb::SectionType section_type = section_sp->GetType(); - switch (section_type) { - case eSectionTypeInvalid: - return AddressClass::eUnknown; - - case eSectionTypeCode: - if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) { - // For ARM we have a bit in the n_desc field of the symbol that - // tells us ARM/Thumb which is bit 0x0008. - if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB) - return AddressClass::eCodeAlternateISA; - } - return AddressClass::eCode; - - case eSectionTypeContainer: - return AddressClass::eUnknown; - - case eSectionTypeData: - case eSectionTypeDataCString: - case eSectionTypeDataCStringPointers: - case eSectionTypeDataSymbolAddress: - case eSectionTypeData4: - case eSectionTypeData8: - case eSectionTypeData16: - case eSectionTypeDataPointers: - case eSectionTypeZeroFill: - case eSectionTypeDataObjCMessageRefs: - case eSectionTypeDataObjCCFStrings: - case eSectionTypeGoSymtab: - return AddressClass::eData; - - case eSectionTypeDebug: - case eSectionTypeDWARFDebugAbbrev: - case eSectionTypeDWARFDebugAbbrevDwo: - case eSectionTypeDWARFDebugAddr: - case eSectionTypeDWARFDebugAranges: - case eSectionTypeDWARFDebugCuIndex: - case eSectionTypeDWARFDebugFrame: - case eSectionTypeDWARFDebugInfo: - case eSectionTypeDWARFDebugInfoDwo: - case eSectionTypeDWARFDebugLine: - case eSectionTypeDWARFDebugLineStr: - case eSectionTypeDWARFDebugLoc: - case eSectionTypeDWARFDebugLocLists: - case eSectionTypeDWARFDebugMacInfo: - case eSectionTypeDWARFDebugMacro: - case eSectionTypeDWARFDebugNames: - case eSectionTypeDWARFDebugPubNames: - case eSectionTypeDWARFDebugPubTypes: - case eSectionTypeDWARFDebugRanges: - case eSectionTypeDWARFDebugRngLists: - case eSectionTypeDWARFDebugStr: - case eSectionTypeDWARFDebugStrDwo: - case eSectionTypeDWARFDebugStrOffsets: - case eSectionTypeDWARFDebugStrOffsetsDwo: - case eSectionTypeDWARFDebugTypes: - case eSectionTypeDWARFAppleNames: - case eSectionTypeDWARFAppleTypes: - case eSectionTypeDWARFAppleNamespaces: - case eSectionTypeDWARFAppleObjC: - case eSectionTypeDWARFGNUDebugAltLink: - return AddressClass::eDebug; - - case eSectionTypeEHFrame: - case eSectionTypeARMexidx: - case eSectionTypeARMextab: - case eSectionTypeCompactUnwind: - return AddressClass::eRuntime; - - case eSectionTypeAbsoluteAddress: - case eSectionTypeELFSymbolTable: - case eSectionTypeELFDynamicSymbols: - case eSectionTypeELFRelocationEntries: - case eSectionTypeELFDynamicLinkInfo: - case eSectionTypeOther: - return AddressClass::eUnknown; - } - } - } - - const SymbolType symbol_type = symbol->GetType(); - switch (symbol_type) { - case eSymbolTypeAny: - return AddressClass::eUnknown; - case eSymbolTypeAbsolute: - return AddressClass::eUnknown; - - case eSymbolTypeCode: - case eSymbolTypeTrampoline: - case eSymbolTypeResolver: - if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) { - // For ARM we have a bit in the n_desc field of the symbol that tells - // us ARM/Thumb which is bit 0x0008. - if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB) - return AddressClass::eCodeAlternateISA; - } - return AddressClass::eCode; - - case eSymbolTypeData: - return AddressClass::eData; - case eSymbolTypeRuntime: - return AddressClass::eRuntime; - case eSymbolTypeException: - return AddressClass::eRuntime; - case eSymbolTypeSourceFile: - return AddressClass::eDebug; - case eSymbolTypeHeaderFile: - return AddressClass::eDebug; - case eSymbolTypeObjectFile: - return AddressClass::eDebug; - case eSymbolTypeCommonBlock: - return AddressClass::eDebug; - case eSymbolTypeBlock: - return AddressClass::eDebug; - case eSymbolTypeLocal: - return AddressClass::eData; - case eSymbolTypeParam: - return AddressClass::eData; - case eSymbolTypeVariable: - return AddressClass::eData; - case eSymbolTypeVariableType: - return AddressClass::eDebug; - case eSymbolTypeLineEntry: - return AddressClass::eDebug; - case eSymbolTypeLineHeader: - return AddressClass::eDebug; - case eSymbolTypeScopeBegin: - return AddressClass::eDebug; - case eSymbolTypeScopeEnd: - return AddressClass::eDebug; - case eSymbolTypeAdditional: - return AddressClass::eUnknown; - case eSymbolTypeCompiler: - return AddressClass::eDebug; - case eSymbolTypeInstrumentation: - return AddressClass::eDebug; - case eSymbolTypeUndefined: - return AddressClass::eUnknown; - case eSymbolTypeObjCClass: - return AddressClass::eRuntime; - case eSymbolTypeObjCMetaClass: - return AddressClass::eRuntime; - case eSymbolTypeObjCIVar: - return AddressClass::eRuntime; - case eSymbolTypeReExported: - return AddressClass::eRuntime; - } - } - } - return AddressClass::eUnknown; -} - -Symtab *ObjectFileMachO::GetSymtab() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_symtab_ap.get() == NULL) { - m_symtab_ap.reset(new Symtab(this)); - std::lock_guard<std::recursive_mutex> symtab_guard( - m_symtab_ap->GetMutex()); - ParseSymtab(); - m_symtab_ap->Finalize(); - } - } - return m_symtab_ap.get(); -} - -bool ObjectFileMachO::IsStripped() { - if (m_dysymtab.cmd == 0) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - - load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == LC_DYSYMTAB) { - m_dysymtab.cmd = lc.cmd; - m_dysymtab.cmdsize = lc.cmdsize; - if (m_data.GetU32(&offset, &m_dysymtab.ilocalsym, - (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2) == - NULL) { - // Clear m_dysymtab if we were unable to read all items from the - // load command - ::memset(&m_dysymtab, 0, sizeof(m_dysymtab)); - } - } - offset = load_cmd_offset + lc.cmdsize; - } - } - } - if (m_dysymtab.cmd) - return m_dysymtab.nlocalsym <= 1; - return false; -} - -ObjectFileMachO::EncryptedFileRanges ObjectFileMachO::GetEncryptedFileRanges() { - EncryptedFileRanges result; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - - encryption_info_command encryption_cmd; - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL) - break; - - // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for the - // 3 fields we care about, so treat them the same. - if (encryption_cmd.cmd == LC_ENCRYPTION_INFO || - encryption_cmd.cmd == LC_ENCRYPTION_INFO_64) { - if (m_data.GetU32(&offset, &encryption_cmd.cryptoff, 3)) { - if (encryption_cmd.cryptid != 0) { - EncryptedFileRanges::Entry entry; - entry.SetRangeBase(encryption_cmd.cryptoff); - entry.SetByteSize(encryption_cmd.cryptsize); - result.Append(entry); - } - } - } - offset = load_cmd_offset + encryption_cmd.cmdsize; - } - - return result; -} - -void ObjectFileMachO::SanitizeSegmentCommand(segment_command_64 &seg_cmd, - uint32_t cmd_idx) { - if (m_length == 0 || seg_cmd.filesize == 0) - return; - - if (seg_cmd.fileoff > m_length) { - // We have a load command that says it extends past the end of the file. - // This is likely a corrupt file. We don't have any way to return an error - // condition here (this method was likely invoked from something like - // ObjectFile::GetSectionList()), so we just null out the section contents, - // and dump a message to stdout. The most common case here is core file - // debugging with a truncated file. - const char *lc_segment_name = - seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT"; - GetModule()->ReportWarning( - "load command %u %s has a fileoff (0x%" PRIx64 - ") that extends beyond the end of the file (0x%" PRIx64 - "), ignoring this section", - cmd_idx, lc_segment_name, seg_cmd.fileoff, m_length); - - seg_cmd.fileoff = 0; - seg_cmd.filesize = 0; - } - - if (seg_cmd.fileoff + seg_cmd.filesize > m_length) { - // We have a load command that says it extends past the end of the file. - // This is likely a corrupt file. We don't have any way to return an error - // condition here (this method was likely invoked from something like - // ObjectFile::GetSectionList()), so we just null out the section contents, - // and dump a message to stdout. The most common case here is core file - // debugging with a truncated file. - const char *lc_segment_name = - seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT"; - GetModule()->ReportWarning( - "load command %u %s has a fileoff + filesize (0x%" PRIx64 - ") that extends beyond the end of the file (0x%" PRIx64 - "), the segment will be truncated to match", - cmd_idx, lc_segment_name, seg_cmd.fileoff + seg_cmd.filesize, m_length); - - // Truncate the length - seg_cmd.filesize = m_length - seg_cmd.fileoff; - } -} - -static uint32_t GetSegmentPermissions(const segment_command_64 &seg_cmd) { - uint32_t result = 0; - if (seg_cmd.initprot & VM_PROT_READ) - result |= ePermissionsReadable; - if (seg_cmd.initprot & VM_PROT_WRITE) - result |= ePermissionsWritable; - if (seg_cmd.initprot & VM_PROT_EXECUTE) - result |= ePermissionsExecutable; - return result; -} - -static lldb::SectionType GetSectionType(uint32_t flags, - ConstString section_name) { - - if (flags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS)) - return eSectionTypeCode; - - uint32_t mach_sect_type = flags & SECTION_TYPE; - static ConstString g_sect_name_objc_data("__objc_data"); - static ConstString g_sect_name_objc_msgrefs("__objc_msgrefs"); - static ConstString g_sect_name_objc_selrefs("__objc_selrefs"); - static ConstString g_sect_name_objc_classrefs("__objc_classrefs"); - static ConstString g_sect_name_objc_superrefs("__objc_superrefs"); - static ConstString g_sect_name_objc_const("__objc_const"); - static ConstString g_sect_name_objc_classlist("__objc_classlist"); - static ConstString g_sect_name_cfstring("__cfstring"); - - static ConstString g_sect_name_dwarf_debug_abbrev("__debug_abbrev"); - static ConstString g_sect_name_dwarf_debug_aranges("__debug_aranges"); - static ConstString g_sect_name_dwarf_debug_frame("__debug_frame"); - static ConstString g_sect_name_dwarf_debug_info("__debug_info"); - static ConstString g_sect_name_dwarf_debug_line("__debug_line"); - static ConstString g_sect_name_dwarf_debug_loc("__debug_loc"); - static ConstString g_sect_name_dwarf_debug_loclists("__debug_loclists"); - static ConstString g_sect_name_dwarf_debug_macinfo("__debug_macinfo"); - static ConstString g_sect_name_dwarf_debug_names("__debug_names"); - static ConstString g_sect_name_dwarf_debug_pubnames("__debug_pubnames"); - static ConstString g_sect_name_dwarf_debug_pubtypes("__debug_pubtypes"); - static ConstString g_sect_name_dwarf_debug_ranges("__debug_ranges"); - static ConstString g_sect_name_dwarf_debug_str("__debug_str"); - static ConstString g_sect_name_dwarf_debug_types("__debug_types"); - static ConstString g_sect_name_dwarf_apple_names("__apple_names"); - static ConstString g_sect_name_dwarf_apple_types("__apple_types"); - static ConstString g_sect_name_dwarf_apple_namespaces("__apple_namespac"); - static ConstString g_sect_name_dwarf_apple_objc("__apple_objc"); - static ConstString g_sect_name_eh_frame("__eh_frame"); - static ConstString g_sect_name_compact_unwind("__unwind_info"); - static ConstString g_sect_name_text("__text"); - static ConstString g_sect_name_data("__data"); - static ConstString g_sect_name_go_symtab("__gosymtab"); - - if (section_name == g_sect_name_dwarf_debug_abbrev) - return eSectionTypeDWARFDebugAbbrev; - if (section_name == g_sect_name_dwarf_debug_aranges) - return eSectionTypeDWARFDebugAranges; - if (section_name == g_sect_name_dwarf_debug_frame) - return eSectionTypeDWARFDebugFrame; - if (section_name == g_sect_name_dwarf_debug_info) - return eSectionTypeDWARFDebugInfo; - if (section_name == g_sect_name_dwarf_debug_line) - return eSectionTypeDWARFDebugLine; - if (section_name == g_sect_name_dwarf_debug_loc) - return eSectionTypeDWARFDebugLoc; - if (section_name == g_sect_name_dwarf_debug_loclists) - return eSectionTypeDWARFDebugLocLists; - if (section_name == g_sect_name_dwarf_debug_macinfo) - return eSectionTypeDWARFDebugMacInfo; - if (section_name == g_sect_name_dwarf_debug_names) - return eSectionTypeDWARFDebugNames; - if (section_name == g_sect_name_dwarf_debug_pubnames) - return eSectionTypeDWARFDebugPubNames; - if (section_name == g_sect_name_dwarf_debug_pubtypes) - return eSectionTypeDWARFDebugPubTypes; - if (section_name == g_sect_name_dwarf_debug_ranges) - return eSectionTypeDWARFDebugRanges; - if (section_name == g_sect_name_dwarf_debug_str) - return eSectionTypeDWARFDebugStr; - if (section_name == g_sect_name_dwarf_debug_types) - return eSectionTypeDWARFDebugTypes; - if (section_name == g_sect_name_dwarf_apple_names) - return eSectionTypeDWARFAppleNames; - if (section_name == g_sect_name_dwarf_apple_types) - return eSectionTypeDWARFAppleTypes; - if (section_name == g_sect_name_dwarf_apple_namespaces) - return eSectionTypeDWARFAppleNamespaces; - if (section_name == g_sect_name_dwarf_apple_objc) - return eSectionTypeDWARFAppleObjC; - if (section_name == g_sect_name_objc_selrefs) - return eSectionTypeDataCStringPointers; - if (section_name == g_sect_name_objc_msgrefs) - return eSectionTypeDataObjCMessageRefs; - if (section_name == g_sect_name_eh_frame) - return eSectionTypeEHFrame; - if (section_name == g_sect_name_compact_unwind) - return eSectionTypeCompactUnwind; - if (section_name == g_sect_name_cfstring) - return eSectionTypeDataObjCCFStrings; - if (section_name == g_sect_name_go_symtab) - return eSectionTypeGoSymtab; - if (section_name == g_sect_name_objc_data || - section_name == g_sect_name_objc_classrefs || - section_name == g_sect_name_objc_superrefs || - section_name == g_sect_name_objc_const || - section_name == g_sect_name_objc_classlist) { - return eSectionTypeDataPointers; - } - - switch (mach_sect_type) { - // TODO: categorize sections by other flags for regular sections - case S_REGULAR: - if (section_name == g_sect_name_text) - return eSectionTypeCode; - if (section_name == g_sect_name_data) - return eSectionTypeData; - return eSectionTypeOther; - case S_ZEROFILL: - return eSectionTypeZeroFill; - case S_CSTRING_LITERALS: // section with only literal C strings - return eSectionTypeDataCString; - case S_4BYTE_LITERALS: // section with only 4 byte literals - return eSectionTypeData4; - case S_8BYTE_LITERALS: // section with only 8 byte literals - return eSectionTypeData8; - case S_LITERAL_POINTERS: // section with only pointers to literals - return eSectionTypeDataPointers; - case S_NON_LAZY_SYMBOL_POINTERS: // section with only non-lazy symbol pointers - return eSectionTypeDataPointers; - case S_LAZY_SYMBOL_POINTERS: // section with only lazy symbol pointers - return eSectionTypeDataPointers; - case S_SYMBOL_STUBS: // section with only symbol stubs, byte size of stub in - // the reserved2 field - return eSectionTypeCode; - case S_MOD_INIT_FUNC_POINTERS: // section with only function pointers for - // initialization - return eSectionTypeDataPointers; - case S_MOD_TERM_FUNC_POINTERS: // section with only function pointers for - // termination - return eSectionTypeDataPointers; - case S_COALESCED: - return eSectionTypeOther; - case S_GB_ZEROFILL: - return eSectionTypeZeroFill; - case S_INTERPOSING: // section with only pairs of function pointers for - // interposing - return eSectionTypeCode; - case S_16BYTE_LITERALS: // section with only 16 byte literals - return eSectionTypeData16; - case S_DTRACE_DOF: - return eSectionTypeDebug; - case S_LAZY_DYLIB_SYMBOL_POINTERS: - return eSectionTypeDataPointers; - default: - return eSectionTypeOther; - } -} - -struct ObjectFileMachO::SegmentParsingContext { - const EncryptedFileRanges EncryptedRanges; - lldb_private::SectionList &UnifiedList; - uint32_t NextSegmentIdx = 0; - uint32_t NextSectionIdx = 0; - bool FileAddressesChanged = false; - - SegmentParsingContext(EncryptedFileRanges EncryptedRanges, - lldb_private::SectionList &UnifiedList) - : EncryptedRanges(std::move(EncryptedRanges)), UnifiedList(UnifiedList) {} -}; - -void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_, - lldb::offset_t offset, - uint32_t cmd_idx, - SegmentParsingContext &context) { - segment_command_64 load_cmd; - memcpy(&load_cmd, &load_cmd_, sizeof(load_cmd_)); - - if (!m_data.GetU8(&offset, (uint8_t *)load_cmd.segname, 16)) - return; - - ModuleSP module_sp = GetModule(); - const bool is_core = GetType() == eTypeCoreFile; - const bool is_dsym = (m_header.filetype == MH_DSYM); - bool add_section = true; - bool add_to_unified = true; - ConstString const_segname( - load_cmd.segname, - std::min<size_t>(strlen(load_cmd.segname), sizeof(load_cmd.segname))); - - SectionSP unified_section_sp( - context.UnifiedList.FindSectionByName(const_segname)); - if (is_dsym && unified_section_sp) { - if (const_segname == GetSegmentNameLINKEDIT()) { - // We need to keep the __LINKEDIT segment private to this object file - // only - add_to_unified = false; - } else { - // This is the dSYM file and this section has already been created by the - // object file, no need to create it. - add_section = false; - } - } - load_cmd.vmaddr = m_data.GetAddress(&offset); - load_cmd.vmsize = m_data.GetAddress(&offset); - load_cmd.fileoff = m_data.GetAddress(&offset); - load_cmd.filesize = m_data.GetAddress(&offset); - if (!m_data.GetU32(&offset, &load_cmd.maxprot, 4)) - return; - - SanitizeSegmentCommand(load_cmd, cmd_idx); - - const uint32_t segment_permissions = GetSegmentPermissions(load_cmd); - const bool segment_is_encrypted = - (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0; - - // Keep a list of mach segments around in case we need to get at data that - // isn't stored in the abstracted Sections. - m_mach_segments.push_back(load_cmd); - - // Use a segment ID of the segment index shifted left by 8 so they never - // conflict with any of the sections. - SectionSP segment_sp; - if (add_section && (const_segname || is_core)) { - segment_sp.reset(new Section( - module_sp, // Module to which this section belongs - this, // Object file to which this sections belongs - ++context.NextSegmentIdx - << 8, // Section ID is the 1 based segment index - // shifted right by 8 bits as not to collide with any of the 256 - // section IDs that are possible - const_segname, // Name of this section - eSectionTypeContainer, // This section is a container of other - // sections. - load_cmd.vmaddr, // File VM address == addresses as they are - // found in the object file - load_cmd.vmsize, // VM size in bytes of this section - load_cmd.fileoff, // Offset to the data for this section in - // the file - load_cmd.filesize, // Size in bytes of this section as found - // in the file - 0, // Segments have no alignment information - load_cmd.flags)); // Flags for this section - - segment_sp->SetIsEncrypted(segment_is_encrypted); - m_sections_ap->AddSection(segment_sp); - segment_sp->SetPermissions(segment_permissions); - if (add_to_unified) - context.UnifiedList.AddSection(segment_sp); - } else if (unified_section_sp) { - if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) { - // Check to see if the module was read from memory? - if (module_sp->GetObjectFile()->GetBaseAddress().IsValid()) { - // We have a module that is in memory and needs to have its file - // address adjusted. We need to do this because when we load a file - // from memory, its addresses will be slid already, yet the addresses - // in the new symbol file will still be unslid. Since everything is - // stored as section offset, this shouldn't cause any problems. - - // Make sure we've parsed the symbol table from the ObjectFile before - // we go around changing its Sections. - module_sp->GetObjectFile()->GetSymtab(); - // eh_frame would present the same problems but we parse that on a per- - // function basis as-needed so it's more difficult to remove its use of - // the Sections. Realistically, the environments where this code path - // will be taken will not have eh_frame sections. - - unified_section_sp->SetFileAddress(load_cmd.vmaddr); - - // Notify the module that the section addresses have been changed once - // we're done so any file-address caches can be updated. - context.FileAddressesChanged = true; - } - } - m_sections_ap->AddSection(unified_section_sp); - } - - struct section_64 sect64; - ::memset(§64, 0, sizeof(sect64)); - // Push a section into our mach sections for the section at index zero - // (NO_SECT) if we don't have any mach sections yet... - if (m_mach_sections.empty()) - m_mach_sections.push_back(sect64); - uint32_t segment_sect_idx; - const lldb::user_id_t first_segment_sectID = context.NextSectionIdx + 1; - - const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8; - for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects; - ++segment_sect_idx) { - if (m_data.GetU8(&offset, (uint8_t *)sect64.sectname, - sizeof(sect64.sectname)) == NULL) - break; - if (m_data.GetU8(&offset, (uint8_t *)sect64.segname, - sizeof(sect64.segname)) == NULL) - break; - sect64.addr = m_data.GetAddress(&offset); - sect64.size = m_data.GetAddress(&offset); - - if (m_data.GetU32(&offset, §64.offset, num_u32s) == NULL) - break; - - // Keep a list of mach sections around in case we need to get at data that - // isn't stored in the abstracted Sections. - m_mach_sections.push_back(sect64); - - if (add_section) { - ConstString section_name( - sect64.sectname, - std::min<size_t>(strlen(sect64.sectname), sizeof(sect64.sectname))); - if (!const_segname) { - // We have a segment with no name so we need to conjure up segments - // that correspond to the section's segname if there isn't already such - // a section. If there is such a section, we resize the section so that - // it spans all sections. We also mark these sections as fake so - // address matches don't hit if they land in the gaps between the child - // sections. - const_segname.SetTrimmedCStringWithLength(sect64.segname, - sizeof(sect64.segname)); - segment_sp = context.UnifiedList.FindSectionByName(const_segname); - if (segment_sp.get()) { - Section *segment = segment_sp.get(); - // Grow the section size as needed. - const lldb::addr_t sect64_min_addr = sect64.addr; - const lldb::addr_t sect64_max_addr = sect64_min_addr + sect64.size; - const lldb::addr_t curr_seg_byte_size = segment->GetByteSize(); - const lldb::addr_t curr_seg_min_addr = segment->GetFileAddress(); - const lldb::addr_t curr_seg_max_addr = - curr_seg_min_addr + curr_seg_byte_size; - if (sect64_min_addr >= curr_seg_min_addr) { - const lldb::addr_t new_seg_byte_size = - sect64_max_addr - curr_seg_min_addr; - // Only grow the section size if needed - if (new_seg_byte_size > curr_seg_byte_size) - segment->SetByteSize(new_seg_byte_size); - } else { - // We need to change the base address of the segment and adjust the - // child section offsets for all existing children. - const lldb::addr_t slide_amount = - sect64_min_addr - curr_seg_min_addr; - segment->Slide(slide_amount, false); - segment->GetChildren().Slide(-slide_amount, false); - segment->SetByteSize(curr_seg_max_addr - sect64_min_addr); - } - - // Grow the section size as needed. - if (sect64.offset) { - const lldb::addr_t segment_min_file_offset = - segment->GetFileOffset(); - const lldb::addr_t segment_max_file_offset = - segment_min_file_offset + segment->GetFileSize(); - - const lldb::addr_t section_min_file_offset = sect64.offset; - const lldb::addr_t section_max_file_offset = - section_min_file_offset + sect64.size; - const lldb::addr_t new_file_offset = - std::min(section_min_file_offset, segment_min_file_offset); - const lldb::addr_t new_file_size = - std::max(section_max_file_offset, segment_max_file_offset) - - new_file_offset; - segment->SetFileOffset(new_file_offset); - segment->SetFileSize(new_file_size); - } - } else { - // Create a fake section for the section's named segment - segment_sp.reset(new Section( - segment_sp, // Parent section - module_sp, // Module to which this section belongs - this, // Object file to which this section belongs - ++context.NextSegmentIdx - << 8, // Section ID is the 1 based segment index - // shifted right by 8 bits as not to - // collide with any of the 256 section IDs - // that are possible - const_segname, // Name of this section - eSectionTypeContainer, // This section is a container of - // other sections. - sect64.addr, // File VM address == addresses as they are - // found in the object file - sect64.size, // VM size in bytes of this section - sect64.offset, // Offset to the data for this section in - // the file - sect64.offset ? sect64.size : 0, // Size in bytes of - // this section as - // found in the file - sect64.align, - load_cmd.flags)); // Flags for this section - segment_sp->SetIsFake(true); - segment_sp->SetPermissions(segment_permissions); - m_sections_ap->AddSection(segment_sp); - if (add_to_unified) - context.UnifiedList.AddSection(segment_sp); - segment_sp->SetIsEncrypted(segment_is_encrypted); - } - } - assert(segment_sp.get()); - - lldb::SectionType sect_type = GetSectionType(sect64.flags, section_name); - - SectionSP section_sp(new Section( - segment_sp, module_sp, this, ++context.NextSectionIdx, section_name, - sect_type, sect64.addr - segment_sp->GetFileAddress(), sect64.size, - sect64.offset, sect64.offset == 0 ? 0 : sect64.size, sect64.align, - sect64.flags)); - // Set the section to be encrypted to match the segment - - bool section_is_encrypted = false; - if (!segment_is_encrypted && load_cmd.filesize != 0) - section_is_encrypted = context.EncryptedRanges.FindEntryThatContains( - sect64.offset) != NULL; - - section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted); - section_sp->SetPermissions(segment_permissions); - segment_sp->GetChildren().AddSection(section_sp); - - if (segment_sp->IsFake()) { - segment_sp.reset(); - const_segname.Clear(); - } - } - } - if (segment_sp && is_dsym) { - if (first_segment_sectID <= context.NextSectionIdx) { - lldb::user_id_t sect_uid; - for (sect_uid = first_segment_sectID; sect_uid <= context.NextSectionIdx; - ++sect_uid) { - SectionSP curr_section_sp( - segment_sp->GetChildren().FindSectionByID(sect_uid)); - SectionSP next_section_sp; - if (sect_uid + 1 <= context.NextSectionIdx) - next_section_sp = - segment_sp->GetChildren().FindSectionByID(sect_uid + 1); - - if (curr_section_sp.get()) { - if (curr_section_sp->GetByteSize() == 0) { - if (next_section_sp.get() != NULL) - curr_section_sp->SetByteSize(next_section_sp->GetFileAddress() - - curr_section_sp->GetFileAddress()); - else - curr_section_sp->SetByteSize(load_cmd.vmsize); - } - } - } - } - } -} - -void ObjectFileMachO::ProcessDysymtabCommand(const load_command &load_cmd, - lldb::offset_t offset) { - m_dysymtab.cmd = load_cmd.cmd; - m_dysymtab.cmdsize = load_cmd.cmdsize; - m_data.GetU32(&offset, &m_dysymtab.ilocalsym, - (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2); -} - -void ObjectFileMachO::CreateSections(SectionList &unified_section_list) { - if (m_sections_ap) - return; - - m_sections_ap.reset(new SectionList()); - - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - // bool dump_sections = false; - ModuleSP module_sp(GetModule()); - - offset = MachHeaderSizeFromMagic(m_header.magic); - - SegmentParsingContext context(GetEncryptedFileRanges(), unified_section_list); - struct load_command load_cmd; - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64) - ProcessSegmentCommand(load_cmd, offset, i, context); - else if (load_cmd.cmd == LC_DYSYMTAB) - ProcessDysymtabCommand(load_cmd, offset); - - offset = load_cmd_offset + load_cmd.cmdsize; - } - - if (context.FileAddressesChanged && module_sp) - module_sp->SectionFileAddressesChanged(); -} - -class MachSymtabSectionInfo { -public: - MachSymtabSectionInfo(SectionList *section_list) - : m_section_list(section_list), m_section_infos() { - // Get the number of sections down to a depth of 1 to include all segments - // and their sections, but no other sections that may be added for debug - // map or - m_section_infos.resize(section_list->GetNumSections(1)); - } - - SectionSP GetSection(uint8_t n_sect, addr_t file_addr) { - if (n_sect == 0) - return SectionSP(); - if (n_sect < m_section_infos.size()) { - if (!m_section_infos[n_sect].section_sp) { - SectionSP section_sp(m_section_list->FindSectionByID(n_sect)); - m_section_infos[n_sect].section_sp = section_sp; - if (section_sp) { - m_section_infos[n_sect].vm_range.SetBaseAddress( - section_sp->GetFileAddress()); - m_section_infos[n_sect].vm_range.SetByteSize( - section_sp->GetByteSize()); - } else { - Host::SystemLog(Host::eSystemLogError, - "error: unable to find section for section %u\n", - n_sect); - } - } - if (m_section_infos[n_sect].vm_range.Contains(file_addr)) { - // Symbol is in section. - return m_section_infos[n_sect].section_sp; - } else if (m_section_infos[n_sect].vm_range.GetByteSize() == 0 && - m_section_infos[n_sect].vm_range.GetBaseAddress() == - file_addr) { - // Symbol is in section with zero size, but has the same start address - // as the section. This can happen with linker symbols (symbols that - // start with the letter 'l' or 'L'. - return m_section_infos[n_sect].section_sp; - } - } - return m_section_list->FindSectionContainingFileAddress(file_addr); - } - -protected: - struct SectionInfo { - SectionInfo() : vm_range(), section_sp() {} - - VMRange vm_range; - SectionSP section_sp; - }; - SectionList *m_section_list; - std::vector<SectionInfo> m_section_infos; -}; - -struct TrieEntry { - TrieEntry() - : name(), address(LLDB_INVALID_ADDRESS), flags(0), other(0), - import_name() {} - - void Clear() { - name.Clear(); - address = LLDB_INVALID_ADDRESS; - flags = 0; - other = 0; - import_name.Clear(); - } - - void Dump() const { - printf("0x%16.16llx 0x%16.16llx 0x%16.16llx \"%s\"", - static_cast<unsigned long long>(address), - static_cast<unsigned long long>(flags), - static_cast<unsigned long long>(other), name.GetCString()); - if (import_name) - printf(" -> \"%s\"\n", import_name.GetCString()); - else - printf("\n"); - } - ConstString name; - uint64_t address; - uint64_t flags; - uint64_t other; - ConstString import_name; -}; - -struct TrieEntryWithOffset { - lldb::offset_t nodeOffset; - TrieEntry entry; - - TrieEntryWithOffset(lldb::offset_t offset) : nodeOffset(offset), entry() {} - - void Dump(uint32_t idx) const { - printf("[%3u] 0x%16.16llx: ", idx, - static_cast<unsigned long long>(nodeOffset)); - entry.Dump(); - } - - bool operator<(const TrieEntryWithOffset &other) const { - return (nodeOffset < other.nodeOffset); - } -}; - -static bool ParseTrieEntries(DataExtractor &data, lldb::offset_t offset, - const bool is_arm, - std::vector<llvm::StringRef> &nameSlices, - std::set<lldb::addr_t> &resolver_addresses, - std::vector<TrieEntryWithOffset> &output) { - if (!data.ValidOffset(offset)) - return true; - - const uint64_t terminalSize = data.GetULEB128(&offset); - lldb::offset_t children_offset = offset + terminalSize; - if (terminalSize != 0) { - TrieEntryWithOffset e(offset); - e.entry.flags = data.GetULEB128(&offset); - const char *import_name = NULL; - if (e.entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) { - e.entry.address = 0; - e.entry.other = data.GetULEB128(&offset); // dylib ordinal - import_name = data.GetCStr(&offset); - } else { - e.entry.address = data.GetULEB128(&offset); - if (e.entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) { - e.entry.other = data.GetULEB128(&offset); - uint64_t resolver_addr = e.entry.other; - if (is_arm) - resolver_addr &= THUMB_ADDRESS_BIT_MASK; - resolver_addresses.insert(resolver_addr); - } else - e.entry.other = 0; - } - // Only add symbols that are reexport symbols with a valid import name - if (EXPORT_SYMBOL_FLAGS_REEXPORT & e.entry.flags && import_name && - import_name[0]) { - std::string name; - if (!nameSlices.empty()) { - for (auto name_slice : nameSlices) - name.append(name_slice.data(), name_slice.size()); - } - if (name.size() > 1) { - // Skip the leading '_' - e.entry.name.SetCStringWithLength(name.c_str() + 1, name.size() - 1); - } - if (import_name) { - // Skip the leading '_' - e.entry.import_name.SetCString(import_name + 1); - } - output.push_back(e); - } - } - - const uint8_t childrenCount = data.GetU8(&children_offset); - for (uint8_t i = 0; i < childrenCount; ++i) { - const char *cstr = data.GetCStr(&children_offset); - if (cstr) - nameSlices.push_back(llvm::StringRef(cstr)); - else - return false; // Corrupt data - lldb::offset_t childNodeOffset = data.GetULEB128(&children_offset); - if (childNodeOffset) { - if (!ParseTrieEntries(data, childNodeOffset, is_arm, nameSlices, - resolver_addresses, output)) { - return false; - } - } - nameSlices.pop_back(); - } - return true; -} - -// Read the UUID out of a dyld_shared_cache file on-disk. -UUID ObjectFileMachO::GetSharedCacheUUID(FileSpec dyld_shared_cache, - const ByteOrder byte_order, - const uint32_t addr_byte_size) { - UUID dsc_uuid; - DataBufferSP DscData = MapFileData( - dyld_shared_cache, sizeof(struct lldb_copy_dyld_cache_header_v1), 0); - if (!DscData) - return dsc_uuid; - DataExtractor dsc_header_data(DscData, byte_order, addr_byte_size); - - char version_str[7]; - lldb::offset_t offset = 0; - memcpy(version_str, dsc_header_data.GetData(&offset, 6), 6); - version_str[6] = '\0'; - if (strcmp(version_str, "dyld_v") == 0) { - offset = offsetof(struct lldb_copy_dyld_cache_header_v1, uuid); - dsc_uuid = UUID::fromOptionalData( - dsc_header_data.GetData(&offset, sizeof(uuid_t)), sizeof(uuid_t)); - } - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); - if (log && dsc_uuid.IsValid()) { - log->Printf("Shared cache %s has UUID %s", dyld_shared_cache.GetPath().c_str(), - dsc_uuid.GetAsString().c_str()); - } - return dsc_uuid; -} - -size_t ObjectFileMachO::ParseSymtab() { - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, "ObjectFileMachO::ParseSymtab () module = %s", - m_file.GetFilename().AsCString("")); - ModuleSP module_sp(GetModule()); - if (!module_sp) - return 0; - - struct symtab_command symtab_load_command = {0, 0, 0, 0, 0, 0}; - struct linkedit_data_command function_starts_load_command = {0, 0, 0, 0}; - struct dyld_info_command dyld_info = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - typedef AddressDataArray<lldb::addr_t, bool, 100> FunctionStarts; - FunctionStarts function_starts; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - uint32_t i; - FileSpecList dylib_files; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); - static const llvm::StringRef g_objc_v2_prefix_class("_OBJC_CLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_metaclass("_OBJC_METACLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_ivar("_OBJC_IVAR_$_"); - - for (i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - // Read in the load command and load command size - struct load_command lc; - if (m_data.GetU32(&offset, &lc, 2) == NULL) - break; - // Watch for the symbol table load command - switch (lc.cmd) { - case LC_SYMTAB: - symtab_load_command.cmd = lc.cmd; - symtab_load_command.cmdsize = lc.cmdsize; - // Read in the rest of the symtab load command - if (m_data.GetU32(&offset, &symtab_load_command.symoff, 4) == - 0) // fill in symoff, nsyms, stroff, strsize fields - return 0; - if (symtab_load_command.symoff == 0) { - if (log) - module_sp->LogMessage(log, "LC_SYMTAB.symoff == 0"); - return 0; - } - - if (symtab_load_command.stroff == 0) { - if (log) - module_sp->LogMessage(log, "LC_SYMTAB.stroff == 0"); - return 0; - } - - if (symtab_load_command.nsyms == 0) { - if (log) - module_sp->LogMessage(log, "LC_SYMTAB.nsyms == 0"); - return 0; - } - - if (symtab_load_command.strsize == 0) { - if (log) - module_sp->LogMessage(log, "LC_SYMTAB.strsize == 0"); - return 0; - } - break; - - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - if (m_data.GetU32(&offset, &dyld_info.rebase_off, 10)) { - dyld_info.cmd = lc.cmd; - dyld_info.cmdsize = lc.cmdsize; - } else { - memset(&dyld_info, 0, sizeof(dyld_info)); - } - break; - - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOADFVMLIB: - case LC_LOAD_UPWARD_DYLIB: { - uint32_t name_offset = cmd_offset + m_data.GetU32(&offset); - const char *path = m_data.PeekCStr(name_offset); - if (path) { - FileSpec file_spec(path); - // Strip the path if there is @rpath, @executable, etc so we just use - // the basename - if (path[0] == '@') - file_spec.GetDirectory().Clear(); - - if (lc.cmd == LC_REEXPORT_DYLIB) { - m_reexported_dylibs.AppendIfUnique(file_spec); - } - - dylib_files.Append(file_spec); - } - } break; - - case LC_FUNCTION_STARTS: - function_starts_load_command.cmd = lc.cmd; - function_starts_load_command.cmdsize = lc.cmdsize; - if (m_data.GetU32(&offset, &function_starts_load_command.dataoff, 2) == - NULL) // fill in symoff, nsyms, stroff, strsize fields - memset(&function_starts_load_command, 0, - sizeof(function_starts_load_command)); - break; - - default: - break; - } - offset = cmd_offset + lc.cmdsize; - } - - if (symtab_load_command.cmd) { - Symtab *symtab = m_symtab_ap.get(); - SectionList *section_list = GetSectionList(); - if (section_list == NULL) - return 0; - - const uint32_t addr_byte_size = m_data.GetAddressByteSize(); - const ByteOrder byte_order = m_data.GetByteOrder(); - bool bit_width_32 = addr_byte_size == 4; - const size_t nlist_byte_size = - bit_width_32 ? sizeof(struct nlist) : sizeof(struct nlist_64); - - DataExtractor nlist_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor strtab_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor function_starts_data(NULL, 0, byte_order, addr_byte_size); - DataExtractor indirect_symbol_index_data(NULL, 0, byte_order, - addr_byte_size); - DataExtractor dyld_trie_data(NULL, 0, byte_order, addr_byte_size); - - const addr_t nlist_data_byte_size = - symtab_load_command.nsyms * nlist_byte_size; - const addr_t strtab_data_byte_size = symtab_load_command.strsize; - addr_t strtab_addr = LLDB_INVALID_ADDRESS; - - ProcessSP process_sp(m_process_wp.lock()); - Process *process = process_sp.get(); - - uint32_t memory_module_load_level = eMemoryModuleLoadLevelComplete; - - if (process && m_header.filetype != llvm::MachO::MH_OBJECT) { - Target &target = process->GetTarget(); - - memory_module_load_level = target.GetMemoryModuleLoadLevel(); - - SectionSP linkedit_section_sp( - section_list->FindSectionByName(GetSegmentNameLINKEDIT())); - // Reading mach file from memory in a process or core file... - - if (linkedit_section_sp) { - addr_t linkedit_load_addr = - linkedit_section_sp->GetLoadBaseAddress(&target); - if (linkedit_load_addr == LLDB_INVALID_ADDRESS) { - // We might be trying to access the symbol table before the - // __LINKEDIT's load address has been set in the target. We can't - // fail to read the symbol table, so calculate the right address - // manually - linkedit_load_addr = CalculateSectionLoadAddressForMemoryImage( - m_memory_addr, GetMachHeaderSection(), linkedit_section_sp.get()); - } - - const addr_t linkedit_file_offset = - linkedit_section_sp->GetFileOffset(); - const addr_t symoff_addr = linkedit_load_addr + - symtab_load_command.symoff - - linkedit_file_offset; - strtab_addr = linkedit_load_addr + symtab_load_command.stroff - - linkedit_file_offset; - - bool data_was_read = false; - -#if defined(__APPLE__) && \ - (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) - if (m_header.flags & 0x80000000u && - process->GetAddressByteSize() == sizeof(void *)) { - // This mach-o memory file is in the dyld shared cache. If this - // program is not remote and this is iOS, then this process will - // share the same shared cache as the process we are debugging and we - // can read the entire __LINKEDIT from the address space in this - // process. This is a needed optimization that is used for local iOS - // debugging only since all shared libraries in the shared cache do - // not have corresponding files that exist in the file system of the - // device. They have been combined into a single file. This means we - // always have to load these files from memory. All of the symbol and - // string tables from all of the __LINKEDIT sections from the shared - // libraries in the shared cache have been merged into a single large - // symbol and string table. Reading all of this symbol and string - // table data across can slow down debug launch times, so we optimize - // this by reading the memory for the __LINKEDIT section from this - // process. - - UUID lldb_shared_cache; - addr_t lldb_shared_cache_addr; - GetLLDBSharedCacheUUID (lldb_shared_cache_addr, lldb_shared_cache); - UUID process_shared_cache; - addr_t process_shared_cache_addr; - GetProcessSharedCacheUUID(process, process_shared_cache_addr, process_shared_cache); - bool use_lldb_cache = true; - if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() && - (lldb_shared_cache != process_shared_cache - || process_shared_cache_addr != lldb_shared_cache_addr)) { - use_lldb_cache = false; - } - - PlatformSP platform_sp(target.GetPlatform()); - if (platform_sp && platform_sp->IsHost() && use_lldb_cache) { - data_was_read = true; - nlist_data.SetData((void *)symoff_addr, nlist_data_byte_size, - eByteOrderLittle); - strtab_data.SetData((void *)strtab_addr, strtab_data_byte_size, - eByteOrderLittle); - if (function_starts_load_command.cmd) { - const addr_t func_start_addr = - linkedit_load_addr + function_starts_load_command.dataoff - - linkedit_file_offset; - function_starts_data.SetData( - (void *)func_start_addr, - function_starts_load_command.datasize, eByteOrderLittle); - } - } - } -#endif - - if (!data_was_read) { - // Always load dyld - the dynamic linker - from memory if we didn't - // find a binary anywhere else. lldb will not register - // dylib/framework/bundle loads/unloads if we don't have the dyld - // symbols, we force dyld to load from memory despite the user's - // target.memory-module-load-level setting. - if (memory_module_load_level == eMemoryModuleLoadLevelComplete || - m_header.filetype == llvm::MachO::MH_DYLINKER) { - DataBufferSP nlist_data_sp( - ReadMemory(process_sp, symoff_addr, nlist_data_byte_size)); - if (nlist_data_sp) - nlist_data.SetData(nlist_data_sp, 0, - nlist_data_sp->GetByteSize()); - if (m_dysymtab.nindirectsyms != 0) { - const addr_t indirect_syms_addr = linkedit_load_addr + - m_dysymtab.indirectsymoff - - linkedit_file_offset; - DataBufferSP indirect_syms_data_sp( - ReadMemory(process_sp, indirect_syms_addr, - m_dysymtab.nindirectsyms * 4)); - if (indirect_syms_data_sp) - indirect_symbol_index_data.SetData( - indirect_syms_data_sp, 0, - indirect_syms_data_sp->GetByteSize()); - // If this binary is outside the shared cache, - // cache the string table. - // Binaries in the shared cache all share a giant string table, and - // we can't share the string tables across multiple ObjectFileMachO's, - // so we'd end up re-reading this mega-strtab for every binary - // in the shared cache - it would be a big perf problem. - // For binaries outside the shared cache, it's faster to read the - // entire strtab at once instead of piece-by-piece as we process - // the nlist records. - if ((m_header.flags & 0x80000000u) == 0) { - DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr, - strtab_data_byte_size)); - if (strtab_data_sp) { - strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize()); - } - } - } - } - if (memory_module_load_level >= - eMemoryModuleLoadLevelPartial) { - if (function_starts_load_command.cmd) { - const addr_t func_start_addr = - linkedit_load_addr + function_starts_load_command.dataoff - - linkedit_file_offset; - DataBufferSP func_start_data_sp( - ReadMemory(process_sp, func_start_addr, - function_starts_load_command.datasize)); - if (func_start_data_sp) - function_starts_data.SetData(func_start_data_sp, 0, - func_start_data_sp->GetByteSize()); - } - } - } - } - } else { - nlist_data.SetData(m_data, symtab_load_command.symoff, - nlist_data_byte_size); - strtab_data.SetData(m_data, symtab_load_command.stroff, - strtab_data_byte_size); - - if (dyld_info.export_size > 0) { - dyld_trie_data.SetData(m_data, dyld_info.export_off, - dyld_info.export_size); - } - - if (m_dysymtab.nindirectsyms != 0) { - indirect_symbol_index_data.SetData(m_data, m_dysymtab.indirectsymoff, - m_dysymtab.nindirectsyms * 4); - } - if (function_starts_load_command.cmd) { - function_starts_data.SetData(m_data, - function_starts_load_command.dataoff, - function_starts_load_command.datasize); - } - } - - if (nlist_data.GetByteSize() == 0 && - memory_module_load_level == eMemoryModuleLoadLevelComplete) { - if (log) - module_sp->LogMessage(log, "failed to read nlist data"); - return 0; - } - - const bool have_strtab_data = strtab_data.GetByteSize() > 0; - if (!have_strtab_data) { - if (process) { - if (strtab_addr == LLDB_INVALID_ADDRESS) { - if (log) - module_sp->LogMessage(log, "failed to locate the strtab in memory"); - return 0; - } - } else { - if (log) - module_sp->LogMessage(log, "failed to read strtab data"); - return 0; - } - } - - const ConstString &g_segment_name_TEXT = GetSegmentNameTEXT(); - const ConstString &g_segment_name_DATA = GetSegmentNameDATA(); - const ConstString &g_segment_name_DATA_DIRTY = GetSegmentNameDATA_DIRTY(); - const ConstString &g_segment_name_DATA_CONST = GetSegmentNameDATA_CONST(); - const ConstString &g_segment_name_OBJC = GetSegmentNameOBJC(); - const ConstString &g_section_name_eh_frame = GetSectionNameEHFrame(); - SectionSP text_section_sp( - section_list->FindSectionByName(g_segment_name_TEXT)); - SectionSP data_section_sp( - section_list->FindSectionByName(g_segment_name_DATA)); - SectionSP data_dirty_section_sp( - section_list->FindSectionByName(g_segment_name_DATA_DIRTY)); - SectionSP data_const_section_sp( - section_list->FindSectionByName(g_segment_name_DATA_CONST)); - SectionSP objc_section_sp( - section_list->FindSectionByName(g_segment_name_OBJC)); - SectionSP eh_frame_section_sp; - if (text_section_sp.get()) - eh_frame_section_sp = text_section_sp->GetChildren().FindSectionByName( - g_section_name_eh_frame); - else - eh_frame_section_sp = - section_list->FindSectionByName(g_section_name_eh_frame); - - const bool is_arm = (m_header.cputype == llvm::MachO::CPU_TYPE_ARM); - - // lldb works best if it knows the start address of all functions in a - // module. Linker symbols or debug info are normally the best source of - // information for start addr / size but they may be stripped in a released - // binary. Two additional sources of information exist in Mach-O binaries: - // LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each - // function's start address in the - // binary, relative to the text section. - // eh_frame - the eh_frame FDEs have the start addr & size of - // each function - // LC_FUNCTION_STARTS is the fastest source to read in, and is present on - // all modern binaries. - // Binaries built to run on older releases may need to use eh_frame - // information. - - if (text_section_sp && function_starts_data.GetByteSize()) { - FunctionStarts::Entry function_start_entry; - function_start_entry.data = false; - lldb::offset_t function_start_offset = 0; - function_start_entry.addr = text_section_sp->GetFileAddress(); - uint64_t delta; - while ((delta = function_starts_data.GetULEB128(&function_start_offset)) > - 0) { - // Now append the current entry - function_start_entry.addr += delta; - function_starts.Append(function_start_entry); - } - } else { - // If m_type is eTypeDebugInfo, then this is a dSYM - it will have the - // load command claiming an eh_frame but it doesn't actually have the - // eh_frame content. And if we have a dSYM, we don't need to do any of - // this fill-in-the-missing-symbols works anyway - the debug info should - // give us all the functions in the module. - if (text_section_sp.get() && eh_frame_section_sp.get() && - m_type != eTypeDebugInfo) { - DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp, - DWARFCallFrameInfo::EH); - DWARFCallFrameInfo::FunctionAddressAndSizeVector functions; - eh_frame.GetFunctionAddressAndSizeVector(functions); - addr_t text_base_addr = text_section_sp->GetFileAddress(); - size_t count = functions.GetSize(); - for (size_t i = 0; i < count; ++i) { - const DWARFCallFrameInfo::FunctionAddressAndSizeVector::Entry *func = - functions.GetEntryAtIndex(i); - if (func) { - FunctionStarts::Entry function_start_entry; - function_start_entry.addr = func->base - text_base_addr; - function_starts.Append(function_start_entry); - } - } - } - } - - const size_t function_starts_count = function_starts.GetSize(); - - // For user process binaries (executables, dylibs, frameworks, bundles), if - // we don't have LC_FUNCTION_STARTS/eh_frame section in this binary, we're - // going to assume the binary has been stripped. Don't allow assembly - // language instruction emulation because we don't know proper function - // start boundaries. - // - // For all other types of binaries (kernels, stand-alone bare board - // binaries, kexts), they may not have LC_FUNCTION_STARTS / eh_frame - // sections - we should not make any assumptions about them based on that. - if (function_starts_count == 0 && CalculateStrata() == eStrataUser) { - m_allow_assembly_emulation_unwind_plans = false; - Log *unwind_or_symbol_log(lldb_private::GetLogIfAnyCategoriesSet( - LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_UNWIND)); - - if (unwind_or_symbol_log) - module_sp->LogMessage( - unwind_or_symbol_log, - "no LC_FUNCTION_STARTS, will not allow assembly profiled unwinds"); - } - - const user_id_t TEXT_eh_frame_sectID = - eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() - : static_cast<user_id_t>(NO_SECT); - - lldb::offset_t nlist_data_offset = 0; - - uint32_t N_SO_index = UINT32_MAX; - - MachSymtabSectionInfo section_info(section_list); - std::vector<uint32_t> N_FUN_indexes; - std::vector<uint32_t> N_NSYM_indexes; - std::vector<uint32_t> N_INCL_indexes; - std::vector<uint32_t> N_BRAC_indexes; - std::vector<uint32_t> N_COMM_indexes; - typedef std::multimap<uint64_t, uint32_t> ValueToSymbolIndexMap; - typedef std::map<uint32_t, uint32_t> NListIndexToSymbolIndexMap; - typedef std::map<const char *, uint32_t> ConstNameToSymbolIndexMap; - ValueToSymbolIndexMap N_FUN_addr_to_sym_idx; - ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx; - ConstNameToSymbolIndexMap N_GSYM_name_to_sym_idx; - // Any symbols that get merged into another will get an entry in this map - // so we know - NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx; - uint32_t nlist_idx = 0; - Symbol *symbol_ptr = NULL; - - uint32_t sym_idx = 0; - Symbol *sym = NULL; - size_t num_syms = 0; - std::string memory_symbol_name; - uint32_t unmapped_local_symbols_found = 0; - - std::vector<TrieEntryWithOffset> trie_entries; - std::set<lldb::addr_t> resolver_addresses; - - if (dyld_trie_data.GetByteSize() > 0) { - std::vector<llvm::StringRef> nameSlices; - ParseTrieEntries(dyld_trie_data, 0, is_arm, nameSlices, - resolver_addresses, trie_entries); - - ConstString text_segment_name("__TEXT"); - SectionSP text_segment_sp = - GetSectionList()->FindSectionByName(text_segment_name); - if (text_segment_sp) { - const lldb::addr_t text_segment_file_addr = - text_segment_sp->GetFileAddress(); - if (text_segment_file_addr != LLDB_INVALID_ADDRESS) { - for (auto &e : trie_entries) - e.entry.address += text_segment_file_addr; - } - } - } - - typedef std::set<ConstString> IndirectSymbols; - IndirectSymbols indirect_symbol_names; - -#if defined(__APPLE__) && \ - (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) - - // Some recent builds of the dyld_shared_cache (hereafter: DSC) have been - // optimized by moving LOCAL symbols out of the memory mapped portion of - // the DSC. The symbol information has all been retained, but it isn't - // available in the normal nlist data. However, there *are* duplicate - // entries of *some* - // LOCAL symbols in the normal nlist data. To handle this situation - // correctly, we must first attempt - // to parse any DSC unmapped symbol information. If we find any, we set a - // flag that tells the normal nlist parser to ignore all LOCAL symbols. - - if (m_header.flags & 0x80000000u) { - // Before we can start mapping the DSC, we need to make certain the - // target process is actually using the cache we can find. - - // Next we need to determine the correct path for the dyld shared cache. - - ArchSpec header_arch; - GetArchitecture(header_arch); - char dsc_path[PATH_MAX]; - char dsc_path_development[PATH_MAX]; - - snprintf( - dsc_path, sizeof(dsc_path), "%s%s%s", - "/System/Library/Caches/com.apple.dyld/", /* IPHONE_DYLD_SHARED_CACHE_DIR - */ - "dyld_shared_cache_", /* DYLD_SHARED_CACHE_BASE_NAME */ - header_arch.GetArchitectureName()); - - snprintf( - dsc_path_development, sizeof(dsc_path), "%s%s%s%s", - "/System/Library/Caches/com.apple.dyld/", /* IPHONE_DYLD_SHARED_CACHE_DIR - */ - "dyld_shared_cache_", /* DYLD_SHARED_CACHE_BASE_NAME */ - header_arch.GetArchitectureName(), ".development"); - - FileSpec dsc_nondevelopment_filespec(dsc_path, false); - FileSpec dsc_development_filespec(dsc_path_development, false); - FileSpec dsc_filespec; - - UUID dsc_uuid; - UUID process_shared_cache_uuid; - addr_t process_shared_cache_base_addr; - - if (process) { - GetProcessSharedCacheUUID(process, process_shared_cache_base_addr, process_shared_cache_uuid); - } - - // First see if we can find an exact match for the inferior process - // shared cache UUID in the development or non-development shared caches - // on disk. - if (process_shared_cache_uuid.IsValid()) { - if (FileSystem::Instance().Exists(dsc_development_filespec)) { - UUID dsc_development_uuid = GetSharedCacheUUID( - dsc_development_filespec, byte_order, addr_byte_size); - if (dsc_development_uuid.IsValid() && - dsc_development_uuid == process_shared_cache_uuid) { - dsc_filespec = dsc_development_filespec; - dsc_uuid = dsc_development_uuid; - } - } - if (!dsc_uuid.IsValid() && - FileSystem::Instance().Exists(dsc_nondevelopment_filespec)) { - UUID dsc_nondevelopment_uuid = GetSharedCacheUUID( - dsc_nondevelopment_filespec, byte_order, addr_byte_size); - if (dsc_nondevelopment_uuid.IsValid() && - dsc_nondevelopment_uuid == process_shared_cache_uuid) { - dsc_filespec = dsc_nondevelopment_filespec; - dsc_uuid = dsc_nondevelopment_uuid; - } - } - } - - // Failing a UUID match, prefer the development dyld_shared cache if both - // are present. - if (!FileSystem::Instance().Exists(dsc_filespec)) { - if (FileSystem::Instance().Exists(dsc_development_filespec)) { - dsc_filespec = dsc_development_filespec; - } else { - dsc_filespec = dsc_nondevelopment_filespec; - } - } - - /* The dyld_cache_header has a pointer to the - dyld_cache_local_symbols_info structure (localSymbolsOffset). - The dyld_cache_local_symbols_info structure gives us three things: - 1. The start and count of the nlist records in the dyld_shared_cache - file - 2. The start and size of the strings for these nlist records - 3. The start and count of dyld_cache_local_symbols_entry entries - - There is one dyld_cache_local_symbols_entry per dylib/framework in the - dyld shared cache. - The "dylibOffset" field is the Mach-O header of this dylib/framework in - the dyld shared cache. - The dyld_cache_local_symbols_entry also lists the start of this - dylib/framework's nlist records - and the count of how many nlist records there are for this - dylib/framework. - */ - - // Process the dyld shared cache header to find the unmapped symbols - - DataBufferSP dsc_data_sp = MapFileData( - dsc_filespec, sizeof(struct lldb_copy_dyld_cache_header_v1), 0); - if (!dsc_uuid.IsValid()) { - dsc_uuid = GetSharedCacheUUID(dsc_filespec, byte_order, addr_byte_size); - } - if (dsc_data_sp) { - DataExtractor dsc_header_data(dsc_data_sp, byte_order, addr_byte_size); - - bool uuid_match = true; - if (dsc_uuid.IsValid() && process) { - if (process_shared_cache_uuid.IsValid() && - dsc_uuid != process_shared_cache_uuid) { - // The on-disk dyld_shared_cache file is not the same as the one in - // this process' memory, don't use it. - uuid_match = false; - ModuleSP module_sp(GetModule()); - if (module_sp) - module_sp->ReportWarning("process shared cache does not match " - "on-disk dyld_shared_cache file, some " - "symbol names will be missing."); - } - } - - offset = offsetof(struct lldb_copy_dyld_cache_header_v1, mappingOffset); - - uint32_t mappingOffset = dsc_header_data.GetU32(&offset); - - // If the mappingOffset points to a location inside the header, we've - // opened an old dyld shared cache, and should not proceed further. - if (uuid_match && - mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v1)) { - - DataBufferSP dsc_mapping_info_data_sp = MapFileData( - dsc_filespec, sizeof(struct lldb_copy_dyld_cache_mapping_info), - mappingOffset); - - DataExtractor dsc_mapping_info_data(dsc_mapping_info_data_sp, - byte_order, addr_byte_size); - offset = 0; - - // The File addresses (from the in-memory Mach-O load commands) for - // the shared libraries in the shared library cache need to be - // adjusted by an offset to match up with the dylibOffset identifying - // field in the dyld_cache_local_symbol_entry's. This offset is - // recorded in mapping_offset_value. - const uint64_t mapping_offset_value = - dsc_mapping_info_data.GetU64(&offset); - - offset = offsetof(struct lldb_copy_dyld_cache_header_v1, - localSymbolsOffset); - uint64_t localSymbolsOffset = dsc_header_data.GetU64(&offset); - uint64_t localSymbolsSize = dsc_header_data.GetU64(&offset); - - if (localSymbolsOffset && localSymbolsSize) { - // Map the local symbols - DataBufferSP dsc_local_symbols_data_sp = - MapFileData(dsc_filespec, localSymbolsSize, localSymbolsOffset); - - if (dsc_local_symbols_data_sp) { - DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, - byte_order, addr_byte_size); - - offset = 0; - - typedef std::map<ConstString, uint16_t> UndefinedNameToDescMap; - typedef std::map<uint32_t, ConstString> SymbolIndexToName; - UndefinedNameToDescMap undefined_name_to_desc; - SymbolIndexToName reexport_shlib_needs_fixup; - - // Read the local_symbols_infos struct in one shot - struct lldb_copy_dyld_cache_local_symbols_info local_symbols_info; - dsc_local_symbols_data.GetU32(&offset, - &local_symbols_info.nlistOffset, 6); - - SectionSP text_section_sp( - section_list->FindSectionByName(GetSegmentNameTEXT())); - - uint32_t header_file_offset = - (text_section_sp->GetFileAddress() - mapping_offset_value); - - offset = local_symbols_info.entriesOffset; - for (uint32_t entry_index = 0; - entry_index < local_symbols_info.entriesCount; - entry_index++) { - struct lldb_copy_dyld_cache_local_symbols_entry - local_symbols_entry; - local_symbols_entry.dylibOffset = - dsc_local_symbols_data.GetU32(&offset); - local_symbols_entry.nlistStartIndex = - dsc_local_symbols_data.GetU32(&offset); - local_symbols_entry.nlistCount = - dsc_local_symbols_data.GetU32(&offset); - - if (header_file_offset == local_symbols_entry.dylibOffset) { - unmapped_local_symbols_found = local_symbols_entry.nlistCount; - - // The normal nlist code cannot correctly size the Symbols - // array, we need to allocate it here. - sym = symtab->Resize( - symtab_load_command.nsyms + m_dysymtab.nindirectsyms + - unmapped_local_symbols_found - m_dysymtab.nlocalsym); - num_syms = symtab->GetNumSymbols(); - - nlist_data_offset = - local_symbols_info.nlistOffset + - (nlist_byte_size * local_symbols_entry.nlistStartIndex); - uint32_t string_table_offset = - local_symbols_info.stringsOffset; - - for (uint32_t nlist_index = 0; - nlist_index < local_symbols_entry.nlistCount; - nlist_index++) { - ///////////////////////////// - { - struct nlist_64 nlist; - if (!dsc_local_symbols_data.ValidOffsetForDataOfSize( - nlist_data_offset, nlist_byte_size)) - break; - - nlist.n_strx = dsc_local_symbols_data.GetU32_unchecked( - &nlist_data_offset); - nlist.n_type = dsc_local_symbols_data.GetU8_unchecked( - &nlist_data_offset); - nlist.n_sect = dsc_local_symbols_data.GetU8_unchecked( - &nlist_data_offset); - nlist.n_desc = dsc_local_symbols_data.GetU16_unchecked( - &nlist_data_offset); - nlist.n_value = - dsc_local_symbols_data.GetAddress_unchecked( - &nlist_data_offset); - - SymbolType type = eSymbolTypeInvalid; - const char *symbol_name = dsc_local_symbols_data.PeekCStr( - string_table_offset + nlist.n_strx); - - if (symbol_name == NULL) { - // No symbol should be NULL, even the symbols with no - // string values should have an offset zero which - // points to an empty C-string - Host::SystemLog( - Host::eSystemLogError, - "error: DSC unmapped local symbol[%u] has invalid " - "string table offset 0x%x in %s, ignoring symbol\n", - entry_index, nlist.n_strx, - module_sp->GetFileSpec().GetPath().c_str()); - continue; - } - if (symbol_name[0] == '\0') - symbol_name = NULL; - - const char *symbol_name_non_abi_mangled = NULL; - - SectionSP symbol_section; - uint32_t symbol_byte_size = 0; - bool add_nlist = true; - bool is_debug = ((nlist.n_type & N_STAB) != 0); - bool demangled_is_synthesized = false; - bool is_gsym = false; - bool set_value = true; - - assert(sym_idx < num_syms); - - sym[sym_idx].SetDebug(is_debug); - - if (is_debug) { - switch (nlist.n_type) { - case N_GSYM: - // global symbol: name,,NO_SECT,type,0 - // Sometimes the N_GSYM value contains the address. - - // FIXME: In the .o files, we have a GSYM and a debug - // symbol for all the ObjC data. They - // have the same address, but we want to ensure that - // we always find only the real symbol, 'cause we - // don't currently correctly attribute the - // GSYM one to the ObjCClass/Ivar/MetaClass - // symbol type. This is a temporary hack to make - // sure the ObjectiveC symbols get treated correctly. - // To do this right, we should coalesce all the GSYM - // & global symbols that have the same address. - - is_gsym = true; - sym[sym_idx].SetExternal(true); - - if (symbol_name && symbol_name[0] == '_' && - symbol_name[1] == 'O') { - llvm::StringRef symbol_name_ref(symbol_name); - if (symbol_name_ref.startswith( - g_objc_v2_prefix_class)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = - symbol_name + g_objc_v2_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_metaclass)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + - g_objc_v2_prefix_metaclass.size(); - type = eSymbolTypeObjCMetaClass; - demangled_is_synthesized = true; - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_ivar)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = - symbol_name + g_objc_v2_prefix_ivar.size(); - type = eSymbolTypeObjCIVar; - demangled_is_synthesized = true; - } - } else { - if (nlist.n_value != 0) - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - type = eSymbolTypeData; - } - break; - - case N_FNAME: - // procedure name (f77 kludge): name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_FUN: - // procedure: name,,n_sect,linenumber,address - if (symbol_name) { - type = eSymbolTypeCode; - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - - N_FUN_addr_to_sym_idx.insert( - std::make_pair(nlist.n_value, sym_idx)); - // We use the current number of symbols in the - // symbol table in lieu of using nlist_idx in case - // we ever start trimming entries out - N_FUN_indexes.push_back(sym_idx); - } else { - type = eSymbolTypeCompiler; - - if (!N_FUN_indexes.empty()) { - // Copy the size of the function into the - // original - // STAB entry so we don't have - // to hunt for it later - symtab->SymbolAtIndex(N_FUN_indexes.back()) - ->SetByteSize(nlist.n_value); - N_FUN_indexes.pop_back(); - // We don't really need the end function STAB as - // it contains the size which we already placed - // with the original symbol, so don't add it if - // we want a minimal symbol table - add_nlist = false; - } - } - break; - - case N_STSYM: - // static symbol: name,,n_sect,type,address - N_STSYM_addr_to_sym_idx.insert( - std::make_pair(nlist.n_value, sym_idx)); - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - if (symbol_name && symbol_name[0]) { - type = ObjectFile::GetSymbolTypeFromName( - symbol_name + 1, eSymbolTypeData); - } - break; - - case N_LCSYM: - // .lcomm symbol: name,,n_sect,type,address - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - type = eSymbolTypeCommonBlock; - break; - - case N_BNSYM: - // We use the current number of symbols in the symbol - // table in lieu of using nlist_idx in case we ever - // start trimming entries out Skip these if we want - // minimal symbol tables - add_nlist = false; - break; - - case N_ENSYM: - // Set the size of the N_BNSYM to the terminating - // index of this N_ENSYM so that we can always skip - // the entire symbol if we need to navigate more - // quickly at the source level when parsing STABS - // Skip these if we want minimal symbol tables - add_nlist = false; - break; - - case N_OPT: - // emitted with gcc2_compiled and in gcc source - type = eSymbolTypeCompiler; - break; - - case N_RSYM: - // register sym: name,,NO_SECT,type,register - type = eSymbolTypeVariable; - break; - - case N_SLINE: - // src line: 0,,n_sect,linenumber,address - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; - - case N_SSYM: - // structure elt: name,,NO_SECT,type,struct_offset - type = eSymbolTypeVariableType; - break; - - case N_SO: - // source file name - type = eSymbolTypeSourceFile; - if (symbol_name == NULL) { - add_nlist = false; - if (N_SO_index != UINT32_MAX) { - // Set the size of the N_SO to the terminating - // index of this N_SO so that we can always skip - // the entire N_SO if we need to navigate more - // quickly at the source level when parsing STABS - symbol_ptr = symtab->SymbolAtIndex(N_SO_index); - symbol_ptr->SetByteSize(sym_idx); - symbol_ptr->SetSizeIsSibling(true); - } - N_NSYM_indexes.clear(); - N_INCL_indexes.clear(); - N_BRAC_indexes.clear(); - N_COMM_indexes.clear(); - N_FUN_indexes.clear(); - N_SO_index = UINT32_MAX; - } else { - // We use the current number of symbols in the - // symbol table in lieu of using nlist_idx in case - // we ever start trimming entries out - const bool N_SO_has_full_path = - symbol_name[0] == '/'; - if (N_SO_has_full_path) { - if ((N_SO_index == sym_idx - 1) && - ((sym_idx - 1) < num_syms)) { - // We have two consecutive N_SO entries where - // the first contains a directory and the - // second contains a full path. - sym[sym_idx - 1].GetMangled().SetValue( - ConstString(symbol_name), false); - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - add_nlist = false; - } else { - // This is the first entry in a N_SO that - // contains a directory or - // a full path to the source file - N_SO_index = sym_idx; - } - } else if ((N_SO_index == sym_idx - 1) && - ((sym_idx - 1) < num_syms)) { - // This is usually the second N_SO entry that - // contains just the filename, so here we combine - // it with the first one if we are minimizing the - // symbol table - const char *so_path = - sym[sym_idx - 1] - .GetMangled() - .GetDemangledName( - lldb::eLanguageTypeUnknown) - .AsCString(); - if (so_path && so_path[0]) { - std::string full_so_path(so_path); - const size_t double_slash_pos = - full_so_path.find("//"); - if (double_slash_pos != std::string::npos) { - // The linker has been generating bad N_SO - // entries with doubled up paths - // in the format "%s%s" where the first - // string in the DW_AT_comp_dir, and the - // second is the directory for the source - // file so you end up with a path that looks - // like "/tmp/src//tmp/src/" - FileSpec so_dir(so_path, false); - if (!FileSystem::Instance().Exists(so_dir)) { - so_dir.SetFile( - &full_so_path[double_slash_pos + 1], - false); - if (FileSystem::Instance().Exists(so_dir)) { - // Trim off the incorrect path - full_so_path.erase(0, - double_slash_pos + 1); - } - } - } - if (*full_so_path.rbegin() != '/') - full_so_path += '/'; - full_so_path += symbol_name; - sym[sym_idx - 1].GetMangled().SetValue( - ConstString(full_so_path.c_str()), false); - add_nlist = false; - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - } - } else { - // This could be a relative path to a N_SO - N_SO_index = sym_idx; - } - } - break; - - case N_OSO: - // object file name: name,,0,0,st_mtime - type = eSymbolTypeObjectFile; - break; - - case N_LSYM: - // local sym: name,,NO_SECT,type,offset - type = eSymbolTypeLocal; - break; - - //---------------------------------------------------------------------- - // INCL scopes - //---------------------------------------------------------------------- - case N_BINCL: - // include file beginning: name,,NO_SECT,0,sum We use - // the current number of symbols in the symbol table - // in lieu of using nlist_idx in case we ever start - // trimming entries out - N_INCL_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; - - case N_EINCL: - // include file end: name,,NO_SECT,0,0 - // Set the size of the N_BINCL to the terminating - // index of this N_EINCL so that we can always skip - // the entire symbol if we need to navigate more - // quickly at the source level when parsing STABS - if (!N_INCL_indexes.empty()) { - symbol_ptr = - symtab->SymbolAtIndex(N_INCL_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_INCL_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_SOL: - // #included file name: name,,n_sect,0,address - type = eSymbolTypeHeaderFile; - - // We currently don't use the header files on darwin - add_nlist = false; - break; - - case N_PARAMS: - // compiler parameters: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_VERSION: - // compiler version: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_OLEVEL: - // compiler -O level: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_PSYM: - // parameter: name,,NO_SECT,type,offset - type = eSymbolTypeVariable; - break; - - case N_ENTRY: - // alternate entry: name,,n_sect,linenumber,address - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; - - //---------------------------------------------------------------------- - // Left and Right Braces - //---------------------------------------------------------------------- - case N_LBRAC: - // left bracket: 0,,NO_SECT,nesting level,address We - // use the current number of symbols in the symbol - // table in lieu of using nlist_idx in case we ever - // start trimming entries out - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - N_BRAC_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; - - case N_RBRAC: - // right bracket: 0,,NO_SECT,nesting level,address - // Set the size of the N_LBRAC to the terminating - // index of this N_RBRAC so that we can always skip - // the entire symbol if we need to navigate more - // quickly at the source level when parsing STABS - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - if (!N_BRAC_indexes.empty()) { - symbol_ptr = - symtab->SymbolAtIndex(N_BRAC_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_BRAC_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_EXCL: - // deleted include file: name,,NO_SECT,0,sum - type = eSymbolTypeHeaderFile; - break; - - //---------------------------------------------------------------------- - // COMM scopes - //---------------------------------------------------------------------- - case N_BCOMM: - // begin common: name,,NO_SECT,0,0 - // We use the current number of symbols in the symbol - // table in lieu of using nlist_idx in case we ever - // start trimming entries out - type = eSymbolTypeScopeBegin; - N_COMM_indexes.push_back(sym_idx); - break; - - case N_ECOML: - // end common (local name): 0,,n_sect,0,address - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - // Fall through - - case N_ECOMM: - // end common: name,,n_sect,0,0 - // Set the size of the N_BCOMM to the terminating - // index of this N_ECOMM/N_ECOML so that we can - // always skip the entire symbol if we need to - // navigate more quickly at the source level when - // parsing STABS - if (!N_COMM_indexes.empty()) { - symbol_ptr = - symtab->SymbolAtIndex(N_COMM_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_COMM_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_LENG: - // second stab entry with length information - type = eSymbolTypeAdditional; - break; - - default: - break; - } - } else { - // uint8_t n_pext = N_PEXT & nlist.n_type; - uint8_t n_type = N_TYPE & nlist.n_type; - sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0); - - switch (n_type) { - case N_INDR: { - const char *reexport_name_cstr = - strtab_data.PeekCStr(nlist.n_value); - if (reexport_name_cstr && reexport_name_cstr[0]) { - type = eSymbolTypeReExported; - ConstString reexport_name( - reexport_name_cstr + - ((reexport_name_cstr[0] == '_') ? 1 : 0)); - sym[sym_idx].SetReExportedSymbolName(reexport_name); - set_value = false; - reexport_shlib_needs_fixup[sym_idx] = reexport_name; - indirect_symbol_names.insert( - ConstString(symbol_name + - ((symbol_name[0] == '_') ? 1 : 0))); - } else - type = eSymbolTypeUndefined; - } break; - - case N_UNDF: - if (symbol_name && symbol_name[0]) { - ConstString undefined_name( - symbol_name + - ((symbol_name[0] == '_') ? 1 : 0)); - undefined_name_to_desc[undefined_name] = - nlist.n_desc; - } - // Fall through - case N_PBUD: - type = eSymbolTypeUndefined; - break; - - case N_ABS: - type = eSymbolTypeAbsolute; - break; - - case N_SECT: { - symbol_section = section_info.GetSection( - nlist.n_sect, nlist.n_value); - - if (symbol_section == NULL) { - // TODO: warn about this? - add_nlist = false; - break; - } - - if (TEXT_eh_frame_sectID == nlist.n_sect) { - type = eSymbolTypeException; - } else { - uint32_t section_type = - symbol_section->Get() & SECTION_TYPE; - - switch (section_type) { - case S_CSTRING_LITERALS: - type = eSymbolTypeData; - break; // section with only literal C strings - case S_4BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 4 byte literals - case S_8BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 8 byte literals - case S_LITERAL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only pointers to literals - case S_NON_LAZY_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only non-lazy symbol - // pointers - case S_LAZY_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only lazy symbol pointers - case S_SYMBOL_STUBS: - type = eSymbolTypeTrampoline; - break; // section with only symbol stubs, byte - // size of stub in the reserved2 field - case S_MOD_INIT_FUNC_POINTERS: - type = eSymbolTypeCode; - break; // section with only function pointers for - // initialization - case S_MOD_TERM_FUNC_POINTERS: - type = eSymbolTypeCode; - break; // section with only function pointers for - // termination - case S_INTERPOSING: - type = eSymbolTypeTrampoline; - break; // section with only pairs of function - // pointers for interposing - case S_16BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 16 byte literals - case S_DTRACE_DOF: - type = eSymbolTypeInstrumentation; - break; - case S_LAZY_DYLIB_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; - default: - switch (symbol_section->GetType()) { - case lldb::eSectionTypeCode: - type = eSymbolTypeCode; - break; - case eSectionTypeData: - case eSectionTypeDataCString: // Inlined C string - // data - case eSectionTypeDataCStringPointers: // Pointers - // to C - // string - // data - case eSectionTypeDataSymbolAddress: // Address of - // a symbol in - // the symbol - // table - case eSectionTypeData4: - case eSectionTypeData8: - case eSectionTypeData16: - type = eSymbolTypeData; - break; - default: - break; - } - break; - } - - if (type == eSymbolTypeInvalid) { - const char *symbol_sect_name = - symbol_section->GetName().AsCString(); - if (symbol_section->IsDescendant( - text_section_sp.get())) { - if (symbol_section->IsClear( - S_ATTR_PURE_INSTRUCTIONS | - S_ATTR_SELF_MODIFYING_CODE | - S_ATTR_SOME_INSTRUCTIONS)) - type = eSymbolTypeData; - else - type = eSymbolTypeCode; - } else if (symbol_section->IsDescendant( - data_section_sp.get()) || - symbol_section->IsDescendant( - data_dirty_section_sp.get()) || - symbol_section->IsDescendant( - data_const_section_sp.get())) { - if (symbol_sect_name && - ::strstr(symbol_sect_name, "__objc") == - symbol_sect_name) { - type = eSymbolTypeRuntime; - - if (symbol_name) { - llvm::StringRef symbol_name_ref( - symbol_name); - if (symbol_name_ref.startswith("_OBJC_")) { - static const llvm::StringRef - g_objc_v2_prefix_class( - "_OBJC_CLASS_$_"); - static const llvm::StringRef - g_objc_v2_prefix_metaclass( - "_OBJC_METACLASS_$_"); - static const llvm::StringRef - g_objc_v2_prefix_ivar( - "_OBJC_IVAR_$_"); - if (symbol_name_ref.startswith( - g_objc_v2_prefix_class)) { - symbol_name_non_abi_mangled = - symbol_name + 1; - symbol_name = - symbol_name + - g_objc_v2_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - } else if ( - symbol_name_ref.startswith( - g_objc_v2_prefix_metaclass)) { - symbol_name_non_abi_mangled = - symbol_name + 1; - symbol_name = - symbol_name + - g_objc_v2_prefix_metaclass.size(); - type = eSymbolTypeObjCMetaClass; - demangled_is_synthesized = true; - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_ivar)) { - symbol_name_non_abi_mangled = - symbol_name + 1; - symbol_name = - symbol_name + - g_objc_v2_prefix_ivar.size(); - type = eSymbolTypeObjCIVar; - demangled_is_synthesized = true; - } - } - } - } else if (symbol_sect_name && - ::strstr(symbol_sect_name, - "__gcc_except_tab") == - symbol_sect_name) { - type = eSymbolTypeException; - } else { - type = eSymbolTypeData; - } - } else if (symbol_sect_name && - ::strstr(symbol_sect_name, - "__IMPORT") == - symbol_sect_name) { - type = eSymbolTypeTrampoline; - } else if (symbol_section->IsDescendant( - objc_section_sp.get())) { - type = eSymbolTypeRuntime; - if (symbol_name && symbol_name[0] == '.') { - llvm::StringRef symbol_name_ref(symbol_name); - static const llvm::StringRef - g_objc_v1_prefix_class( - ".objc_class_name_"); - if (symbol_name_ref.startswith( - g_objc_v1_prefix_class)) { - symbol_name_non_abi_mangled = symbol_name; - symbol_name = symbol_name + - g_objc_v1_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - } - } - } - } - } - } break; - } - } - - if (add_nlist) { - uint64_t symbol_value = nlist.n_value; - if (symbol_name_non_abi_mangled) { - sym[sym_idx].GetMangled().SetMangledName( - ConstString(symbol_name_non_abi_mangled)); - sym[sym_idx].GetMangled().SetDemangledName( - ConstString(symbol_name)); - } else { - bool symbol_name_is_mangled = false; - - if (symbol_name && symbol_name[0] == '_') { - symbol_name_is_mangled = symbol_name[1] == '_'; - symbol_name++; // Skip the leading underscore - } - - if (symbol_name) { - ConstString const_symbol_name(symbol_name); - sym[sym_idx].GetMangled().SetValue( - const_symbol_name, symbol_name_is_mangled); - if (is_gsym && is_debug) { - const char *gsym_name = - sym[sym_idx] - .GetMangled() - .GetName(lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) - .GetCString(); - if (gsym_name) - N_GSYM_name_to_sym_idx[gsym_name] = sym_idx; - } - } - } - if (symbol_section) { - const addr_t section_file_addr = - symbol_section->GetFileAddress(); - if (symbol_byte_size == 0 && - function_starts_count > 0) { - addr_t symbol_lookup_file_addr = nlist.n_value; - // Do an exact address match for non-ARM addresses, - // else get the closest since the symbol might be a - // thumb symbol which has an address with bit zero - // set - FunctionStarts::Entry *func_start_entry = - function_starts.FindEntry( - symbol_lookup_file_addr, !is_arm); - if (is_arm && func_start_entry) { - // Verify that the function start address is the - // symbol address (ARM) or the symbol address + 1 - // (thumb) - if (func_start_entry->addr != - symbol_lookup_file_addr && - func_start_entry->addr != - (symbol_lookup_file_addr + 1)) { - // Not the right entry, NULL it out... - func_start_entry = NULL; - } - } - if (func_start_entry) { - func_start_entry->data = true; - - addr_t symbol_file_addr = func_start_entry->addr; - uint32_t symbol_flags = 0; - if (is_arm) { - if (symbol_file_addr & 1) - symbol_flags = - MACHO_NLIST_ARM_SYMBOL_IS_THUMB; - symbol_file_addr &= THUMB_ADDRESS_BIT_MASK; - } - - const FunctionStarts::Entry - *next_func_start_entry = - function_starts.FindNextEntry( - func_start_entry); - const addr_t section_end_file_addr = - section_file_addr + - symbol_section->GetByteSize(); - if (next_func_start_entry) { - addr_t next_symbol_file_addr = - next_func_start_entry->addr; - // Be sure the clear the Thumb address bit when - // we calculate the size from the current and - // next address - if (is_arm) - next_symbol_file_addr &= - THUMB_ADDRESS_BIT_MASK; - symbol_byte_size = std::min<lldb::addr_t>( - next_symbol_file_addr - symbol_file_addr, - section_end_file_addr - symbol_file_addr); - } else { - symbol_byte_size = - section_end_file_addr - symbol_file_addr; - } - } - } - symbol_value -= section_file_addr; - } - - if (is_debug == false) { - if (type == eSymbolTypeCode) { - // See if we can find a N_FUN entry for any code - // symbols. If we do find a match, and the name - // matches, then we can merge the two into just the - // function symbol to avoid duplicate entries in - // the symbol table - std::pair<ValueToSymbolIndexMap::const_iterator, - ValueToSymbolIndexMap::const_iterator> - range; - range = N_FUN_addr_to_sym_idx.equal_range( - nlist.n_value); - if (range.first != range.second) { - bool found_it = false; - for (ValueToSymbolIndexMap::const_iterator pos = - range.first; - pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) == - sym[pos->second].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled)) { - m_nlist_idx_to_sym_idx[nlist_idx] = - pos->second; - // We just need the flags from the linker - // symbol, so put these flags - // into the N_FUN flags to avoid duplicate - // symbols in the symbol table - sym[pos->second].SetExternal( - sym[sym_idx].IsExternal()); - sym[pos->second].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - if (resolver_addresses.find(nlist.n_value) != - resolver_addresses.end()) - sym[pos->second].SetType( - eSymbolTypeResolver); - sym[sym_idx].Clear(); - found_it = true; - break; - } - } - if (found_it) - continue; - } else { - if (resolver_addresses.find(nlist.n_value) != - resolver_addresses.end()) - type = eSymbolTypeResolver; - } - } else if (type == eSymbolTypeData || - type == eSymbolTypeObjCClass || - type == eSymbolTypeObjCMetaClass || - type == eSymbolTypeObjCIVar) { - // See if we can find a N_STSYM entry for any data - // symbols. If we do find a match, and the name - // matches, then we can merge the two into just the - // Static symbol to avoid duplicate entries in the - // symbol table - std::pair<ValueToSymbolIndexMap::const_iterator, - ValueToSymbolIndexMap::const_iterator> - range; - range = N_STSYM_addr_to_sym_idx.equal_range( - nlist.n_value); - if (range.first != range.second) { - bool found_it = false; - for (ValueToSymbolIndexMap::const_iterator pos = - range.first; - pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) == - sym[pos->second].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled)) { - m_nlist_idx_to_sym_idx[nlist_idx] = - pos->second; - // We just need the flags from the linker - // symbol, so put these flags - // into the N_STSYM flags to avoid duplicate - // symbols in the symbol table - sym[pos->second].SetExternal( - sym[sym_idx].IsExternal()); - sym[pos->second].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - sym[sym_idx].Clear(); - found_it = true; - break; - } - } - if (found_it) - continue; - } else { - const char *gsym_name = - sym[sym_idx] - .GetMangled() - .GetName(lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) - .GetCString(); - if (gsym_name) { - // Combine N_GSYM stab entries with the non - // stab symbol - ConstNameToSymbolIndexMap::const_iterator pos = - N_GSYM_name_to_sym_idx.find(gsym_name); - if (pos != N_GSYM_name_to_sym_idx.end()) { - const uint32_t GSYM_sym_idx = pos->second; - m_nlist_idx_to_sym_idx[nlist_idx] = - GSYM_sym_idx; - // Copy the address, because often the N_GSYM - // address has an invalid address of zero - // when the global is a common symbol - sym[GSYM_sym_idx].GetAddressRef().SetSection( - symbol_section); - sym[GSYM_sym_idx].GetAddressRef().SetOffset( - symbol_value); - // We just need the flags from the linker - // symbol, so put these flags - // into the N_GSYM flags to avoid duplicate - // symbols in the symbol table - sym[GSYM_sym_idx].SetFlags( - nlist.n_type << 16 | nlist.n_desc); - sym[sym_idx].Clear(); - continue; - } - } - } - } - } - - sym[sym_idx].SetID(nlist_idx); - sym[sym_idx].SetType(type); - if (set_value) { - sym[sym_idx].GetAddressRef().SetSection( - symbol_section); - sym[sym_idx].GetAddressRef().SetOffset(symbol_value); - } - sym[sym_idx].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - - if (symbol_byte_size > 0) - sym[sym_idx].SetByteSize(symbol_byte_size); - - if (demangled_is_synthesized) - sym[sym_idx].SetDemangledNameIsSynthesized(true); - ++sym_idx; - } else { - sym[sym_idx].Clear(); - } - } - ///////////////////////////// - } - break; // No more entries to consider - } - } - - for (const auto &pos : reexport_shlib_needs_fixup) { - const auto undef_pos = undefined_name_to_desc.find(pos.second); - if (undef_pos != undefined_name_to_desc.end()) { - const uint8_t dylib_ordinal = - llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second); - if (dylib_ordinal > 0 && - dylib_ordinal < dylib_files.GetSize()) - sym[pos.first].SetReExportedSymbolSharedLibrary( - dylib_files.GetFileSpecAtIndex(dylib_ordinal - 1)); - } - } - } - } - } - } - } - - // Must reset this in case it was mutated above! - nlist_data_offset = 0; -#endif - - if (nlist_data.GetByteSize() > 0) { - - // If the sym array was not created while parsing the DSC unmapped - // symbols, create it now. - if (sym == NULL) { - sym = symtab->Resize(symtab_load_command.nsyms + - m_dysymtab.nindirectsyms); - num_syms = symtab->GetNumSymbols(); - } - - if (unmapped_local_symbols_found) { - assert(m_dysymtab.ilocalsym == 0); - nlist_data_offset += (m_dysymtab.nlocalsym * nlist_byte_size); - nlist_idx = m_dysymtab.nlocalsym; - } else { - nlist_idx = 0; - } - - typedef std::map<ConstString, uint16_t> UndefinedNameToDescMap; - typedef std::map<uint32_t, ConstString> SymbolIndexToName; - UndefinedNameToDescMap undefined_name_to_desc; - SymbolIndexToName reexport_shlib_needs_fixup; - for (; nlist_idx < symtab_load_command.nsyms; ++nlist_idx) { - struct nlist_64 nlist; - if (!nlist_data.ValidOffsetForDataOfSize(nlist_data_offset, - nlist_byte_size)) - break; - - nlist.n_strx = nlist_data.GetU32_unchecked(&nlist_data_offset); - nlist.n_type = nlist_data.GetU8_unchecked(&nlist_data_offset); - nlist.n_sect = nlist_data.GetU8_unchecked(&nlist_data_offset); - nlist.n_desc = nlist_data.GetU16_unchecked(&nlist_data_offset); - nlist.n_value = nlist_data.GetAddress_unchecked(&nlist_data_offset); - - SymbolType type = eSymbolTypeInvalid; - const char *symbol_name = NULL; - - if (have_strtab_data) { - symbol_name = strtab_data.PeekCStr(nlist.n_strx); - - if (symbol_name == NULL) { - // No symbol should be NULL, even the symbols with no string values - // should have an offset zero which points to an empty C-string - Host::SystemLog(Host::eSystemLogError, - "error: symbol[%u] has invalid string table offset " - "0x%x in %s, ignoring symbol\n", - nlist_idx, nlist.n_strx, - module_sp->GetFileSpec().GetPath().c_str()); - continue; - } - if (symbol_name[0] == '\0') - symbol_name = NULL; - } else { - const addr_t str_addr = strtab_addr + nlist.n_strx; - Status str_error; - if (process->ReadCStringFromMemory(str_addr, memory_symbol_name, - str_error)) - symbol_name = memory_symbol_name.c_str(); - } - const char *symbol_name_non_abi_mangled = NULL; - - SectionSP symbol_section; - lldb::addr_t symbol_byte_size = 0; - bool add_nlist = true; - bool is_gsym = false; - bool is_debug = ((nlist.n_type & N_STAB) != 0); - bool demangled_is_synthesized = false; - bool set_value = true; - assert(sym_idx < num_syms); - - sym[sym_idx].SetDebug(is_debug); - - if (is_debug) { - switch (nlist.n_type) { - case N_GSYM: - // global symbol: name,,NO_SECT,type,0 - // Sometimes the N_GSYM value contains the address. - - // FIXME: In the .o files, we have a GSYM and a debug symbol for all - // the ObjC data. They - // have the same address, but we want to ensure that we always find - // only the real symbol, 'cause we don't currently correctly - // attribute the GSYM one to the ObjCClass/Ivar/MetaClass symbol - // type. This is a temporary hack to make sure the ObjectiveC - // symbols get treated correctly. To do this right, we should - // coalesce all the GSYM & global symbols that have the same - // address. - is_gsym = true; - sym[sym_idx].SetExternal(true); - - if (symbol_name && symbol_name[0] == '_' && symbol_name[1] == 'O') { - llvm::StringRef symbol_name_ref(symbol_name); - if (symbol_name_ref.startswith(g_objc_v2_prefix_class)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_metaclass)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_metaclass.size(); - type = eSymbolTypeObjCMetaClass; - demangled_is_synthesized = true; - } else if (symbol_name_ref.startswith(g_objc_v2_prefix_ivar)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = symbol_name + g_objc_v2_prefix_ivar.size(); - type = eSymbolTypeObjCIVar; - demangled_is_synthesized = true; - } - } else { - if (nlist.n_value != 0) - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - type = eSymbolTypeData; - } - break; - - case N_FNAME: - // procedure name (f77 kludge): name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_FUN: - // procedure: name,,n_sect,linenumber,address - if (symbol_name) { - type = eSymbolTypeCode; - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - - N_FUN_addr_to_sym_idx.insert( - std::make_pair(nlist.n_value, sym_idx)); - // We use the current number of symbols in the symbol table in - // lieu of using nlist_idx in case we ever start trimming entries - // out - N_FUN_indexes.push_back(sym_idx); - } else { - type = eSymbolTypeCompiler; - - if (!N_FUN_indexes.empty()) { - // Copy the size of the function into the original STAB entry - // so we don't have to hunt for it later - symtab->SymbolAtIndex(N_FUN_indexes.back()) - ->SetByteSize(nlist.n_value); - N_FUN_indexes.pop_back(); - // We don't really need the end function STAB as it contains - // the size which we already placed with the original symbol, - // so don't add it if we want a minimal symbol table - add_nlist = false; - } - } - break; - - case N_STSYM: - // static symbol: name,,n_sect,type,address - N_STSYM_addr_to_sym_idx.insert( - std::make_pair(nlist.n_value, sym_idx)); - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - if (symbol_name && symbol_name[0]) { - type = ObjectFile::GetSymbolTypeFromName(symbol_name + 1, - eSymbolTypeData); - } - break; - - case N_LCSYM: - // .lcomm symbol: name,,n_sect,type,address - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - type = eSymbolTypeCommonBlock; - break; - - case N_BNSYM: - // We use the current number of symbols in the symbol table in lieu - // of using nlist_idx in case we ever start trimming entries out - // Skip these if we want minimal symbol tables - add_nlist = false; - break; - - case N_ENSYM: - // Set the size of the N_BNSYM to the terminating index of this - // N_ENSYM so that we can always skip the entire symbol if we need - // to navigate more quickly at the source level when parsing STABS - // Skip these if we want minimal symbol tables - add_nlist = false; - break; - - case N_OPT: - // emitted with gcc2_compiled and in gcc source - type = eSymbolTypeCompiler; - break; - - case N_RSYM: - // register sym: name,,NO_SECT,type,register - type = eSymbolTypeVariable; - break; - - case N_SLINE: - // src line: 0,,n_sect,linenumber,address - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; - - case N_SSYM: - // structure elt: name,,NO_SECT,type,struct_offset - type = eSymbolTypeVariableType; - break; - - case N_SO: - // source file name - type = eSymbolTypeSourceFile; - if (symbol_name == NULL) { - add_nlist = false; - if (N_SO_index != UINT32_MAX) { - // Set the size of the N_SO to the terminating index of this - // N_SO so that we can always skip the entire N_SO if we need - // to navigate more quickly at the source level when parsing - // STABS - symbol_ptr = symtab->SymbolAtIndex(N_SO_index); - symbol_ptr->SetByteSize(sym_idx); - symbol_ptr->SetSizeIsSibling(true); - } - N_NSYM_indexes.clear(); - N_INCL_indexes.clear(); - N_BRAC_indexes.clear(); - N_COMM_indexes.clear(); - N_FUN_indexes.clear(); - N_SO_index = UINT32_MAX; - } else { - // We use the current number of symbols in the symbol table in - // lieu of using nlist_idx in case we ever start trimming entries - // out - const bool N_SO_has_full_path = symbol_name[0] == '/'; - if (N_SO_has_full_path) { - if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) { - // We have two consecutive N_SO entries where the first - // contains a directory and the second contains a full path. - sym[sym_idx - 1].GetMangled().SetValue( - ConstString(symbol_name), false); - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - add_nlist = false; - } else { - // This is the first entry in a N_SO that contains a - // directory or a full path to the source file - N_SO_index = sym_idx; - } - } else if ((N_SO_index == sym_idx - 1) && - ((sym_idx - 1) < num_syms)) { - // This is usually the second N_SO entry that contains just the - // filename, so here we combine it with the first one if we are - // minimizing the symbol table - const char *so_path = - sym[sym_idx - 1] - .GetMangled() - .GetDemangledName(lldb::eLanguageTypeUnknown) - .AsCString(); - if (so_path && so_path[0]) { - std::string full_so_path(so_path); - const size_t double_slash_pos = full_so_path.find("//"); - if (double_slash_pos != std::string::npos) { - // The linker has been generating bad N_SO entries with - // doubled up paths in the format "%s%s" where the first - // string in the DW_AT_comp_dir, and the second is the - // directory for the source file so you end up with a path - // that looks like "/tmp/src//tmp/src/" - FileSpec so_dir(so_path); - if (!FileSystem::Instance().Exists(so_dir)) { - so_dir.SetFile(&full_so_path[double_slash_pos + 1], - FileSpec::Style::native); - if (FileSystem::Instance().Exists(so_dir)) { - // Trim off the incorrect path - full_so_path.erase(0, double_slash_pos + 1); - } - } - } - if (*full_so_path.rbegin() != '/') - full_so_path += '/'; - full_so_path += symbol_name; - sym[sym_idx - 1].GetMangled().SetValue( - ConstString(full_so_path.c_str()), false); - add_nlist = false; - m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1; - } - } else { - // This could be a relative path to a N_SO - N_SO_index = sym_idx; - } - } - break; - - case N_OSO: - // object file name: name,,0,0,st_mtime - type = eSymbolTypeObjectFile; - break; - - case N_LSYM: - // local sym: name,,NO_SECT,type,offset - type = eSymbolTypeLocal; - break; - - //---------------------------------------------------------------------- - // INCL scopes - //---------------------------------------------------------------------- - case N_BINCL: - // include file beginning: name,,NO_SECT,0,sum We use the current - // number of symbols in the symbol table in lieu of using nlist_idx - // in case we ever start trimming entries out - N_INCL_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; - - case N_EINCL: - // include file end: name,,NO_SECT,0,0 - // Set the size of the N_BINCL to the terminating index of this - // N_EINCL so that we can always skip the entire symbol if we need - // to navigate more quickly at the source level when parsing STABS - if (!N_INCL_indexes.empty()) { - symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_INCL_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_SOL: - // #included file name: name,,n_sect,0,address - type = eSymbolTypeHeaderFile; - - // We currently don't use the header files on darwin - add_nlist = false; - break; - - case N_PARAMS: - // compiler parameters: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_VERSION: - // compiler version: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_OLEVEL: - // compiler -O level: name,,NO_SECT,0,0 - type = eSymbolTypeCompiler; - break; - - case N_PSYM: - // parameter: name,,NO_SECT,type,offset - type = eSymbolTypeVariable; - break; - - case N_ENTRY: - // alternate entry: name,,n_sect,linenumber,address - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - type = eSymbolTypeLineEntry; - break; - - //---------------------------------------------------------------------- - // Left and Right Braces - //---------------------------------------------------------------------- - case N_LBRAC: - // left bracket: 0,,NO_SECT,nesting level,address We use the - // current number of symbols in the symbol table in lieu of using - // nlist_idx in case we ever start trimming entries out - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - N_BRAC_indexes.push_back(sym_idx); - type = eSymbolTypeScopeBegin; - break; - - case N_RBRAC: - // right bracket: 0,,NO_SECT,nesting level,address Set the size of - // the N_LBRAC to the terminating index of this N_RBRAC so that we - // can always skip the entire symbol if we need to navigate more - // quickly at the source level when parsing STABS - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - if (!N_BRAC_indexes.empty()) { - symbol_ptr = symtab->SymbolAtIndex(N_BRAC_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_BRAC_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_EXCL: - // deleted include file: name,,NO_SECT,0,sum - type = eSymbolTypeHeaderFile; - break; - - //---------------------------------------------------------------------- - // COMM scopes - //---------------------------------------------------------------------- - case N_BCOMM: - // begin common: name,,NO_SECT,0,0 - // We use the current number of symbols in the symbol table in lieu - // of using nlist_idx in case we ever start trimming entries out - type = eSymbolTypeScopeBegin; - N_COMM_indexes.push_back(sym_idx); - break; - - case N_ECOML: - // end common (local name): 0,,n_sect,0,address - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - LLVM_FALLTHROUGH; - - case N_ECOMM: - // end common: name,,n_sect,0,0 - // Set the size of the N_BCOMM to the terminating index of this - // N_ECOMM/N_ECOML so that we can always skip the entire symbol if - // we need to navigate more quickly at the source level when - // parsing STABS - if (!N_COMM_indexes.empty()) { - symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back()); - symbol_ptr->SetByteSize(sym_idx + 1); - symbol_ptr->SetSizeIsSibling(true); - N_COMM_indexes.pop_back(); - } - type = eSymbolTypeScopeEnd; - break; - - case N_LENG: - // second stab entry with length information - type = eSymbolTypeAdditional; - break; - - default: - break; - } - } else { - // uint8_t n_pext = N_PEXT & nlist.n_type; - uint8_t n_type = N_TYPE & nlist.n_type; - sym[sym_idx].SetExternal((N_EXT & nlist.n_type) != 0); - - switch (n_type) { - case N_INDR: { - const char *reexport_name_cstr = - strtab_data.PeekCStr(nlist.n_value); - if (reexport_name_cstr && reexport_name_cstr[0]) { - type = eSymbolTypeReExported; - ConstString reexport_name( - reexport_name_cstr + - ((reexport_name_cstr[0] == '_') ? 1 : 0)); - sym[sym_idx].SetReExportedSymbolName(reexport_name); - set_value = false; - reexport_shlib_needs_fixup[sym_idx] = reexport_name; - indirect_symbol_names.insert( - ConstString(symbol_name + ((symbol_name[0] == '_') ? 1 : 0))); - } else - type = eSymbolTypeUndefined; - } break; - - case N_UNDF: - if (symbol_name && symbol_name[0]) { - ConstString undefined_name(symbol_name + - ((symbol_name[0] == '_') ? 1 : 0)); - undefined_name_to_desc[undefined_name] = nlist.n_desc; - } - LLVM_FALLTHROUGH; - - case N_PBUD: - type = eSymbolTypeUndefined; - break; - - case N_ABS: - type = eSymbolTypeAbsolute; - break; - - case N_SECT: { - symbol_section = - section_info.GetSection(nlist.n_sect, nlist.n_value); - - if (!symbol_section) { - // TODO: warn about this? - add_nlist = false; - break; - } - - if (TEXT_eh_frame_sectID == nlist.n_sect) { - type = eSymbolTypeException; - } else { - uint32_t section_type = symbol_section->Get() & SECTION_TYPE; - - switch (section_type) { - case S_CSTRING_LITERALS: - type = eSymbolTypeData; - break; // section with only literal C strings - case S_4BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 4 byte literals - case S_8BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 8 byte literals - case S_LITERAL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only pointers to literals - case S_NON_LAZY_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only non-lazy symbol pointers - case S_LAZY_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; // section with only lazy symbol pointers - case S_SYMBOL_STUBS: - type = eSymbolTypeTrampoline; - break; // section with only symbol stubs, byte size of stub in - // the reserved2 field - case S_MOD_INIT_FUNC_POINTERS: - type = eSymbolTypeCode; - break; // section with only function pointers for initialization - case S_MOD_TERM_FUNC_POINTERS: - type = eSymbolTypeCode; - break; // section with only function pointers for termination - case S_INTERPOSING: - type = eSymbolTypeTrampoline; - break; // section with only pairs of function pointers for - // interposing - case S_16BYTE_LITERALS: - type = eSymbolTypeData; - break; // section with only 16 byte literals - case S_DTRACE_DOF: - type = eSymbolTypeInstrumentation; - break; - case S_LAZY_DYLIB_SYMBOL_POINTERS: - type = eSymbolTypeTrampoline; - break; - default: - switch (symbol_section->GetType()) { - case lldb::eSectionTypeCode: - type = eSymbolTypeCode; - break; - case eSectionTypeData: - case eSectionTypeDataCString: // Inlined C string data - case eSectionTypeDataCStringPointers: // Pointers to C string - // data - case eSectionTypeDataSymbolAddress: // Address of a symbol in - // the symbol table - case eSectionTypeData4: - case eSectionTypeData8: - case eSectionTypeData16: - type = eSymbolTypeData; - break; - default: - break; - } - break; - } - - if (type == eSymbolTypeInvalid) { - const char *symbol_sect_name = - symbol_section->GetName().AsCString(); - if (symbol_section->IsDescendant(text_section_sp.get())) { - if (symbol_section->IsClear(S_ATTR_PURE_INSTRUCTIONS | - S_ATTR_SELF_MODIFYING_CODE | - S_ATTR_SOME_INSTRUCTIONS)) - type = eSymbolTypeData; - else - type = eSymbolTypeCode; - } else if (symbol_section->IsDescendant( - data_section_sp.get()) || - symbol_section->IsDescendant( - data_dirty_section_sp.get()) || - symbol_section->IsDescendant( - data_const_section_sp.get())) { - if (symbol_sect_name && - ::strstr(symbol_sect_name, "__objc") == - symbol_sect_name) { - type = eSymbolTypeRuntime; - - if (symbol_name) { - llvm::StringRef symbol_name_ref(symbol_name); - if (symbol_name_ref.startswith("_OBJC_")) { - static const llvm::StringRef g_objc_v2_prefix_class( - "_OBJC_CLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_metaclass( - "_OBJC_METACLASS_$_"); - static const llvm::StringRef g_objc_v2_prefix_ivar( - "_OBJC_IVAR_$_"); - if (symbol_name_ref.startswith( - g_objc_v2_prefix_class)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = - symbol_name + g_objc_v2_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_metaclass)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = - symbol_name + g_objc_v2_prefix_metaclass.size(); - type = eSymbolTypeObjCMetaClass; - demangled_is_synthesized = true; - } else if (symbol_name_ref.startswith( - g_objc_v2_prefix_ivar)) { - symbol_name_non_abi_mangled = symbol_name + 1; - symbol_name = - symbol_name + g_objc_v2_prefix_ivar.size(); - type = eSymbolTypeObjCIVar; - demangled_is_synthesized = true; - } - } - } - } else if (symbol_sect_name && - ::strstr(symbol_sect_name, "__gcc_except_tab") == - symbol_sect_name) { - type = eSymbolTypeException; - } else { - type = eSymbolTypeData; - } - } else if (symbol_sect_name && - ::strstr(symbol_sect_name, "__IMPORT") == - symbol_sect_name) { - type = eSymbolTypeTrampoline; - } else if (symbol_section->IsDescendant( - objc_section_sp.get())) { - type = eSymbolTypeRuntime; - if (symbol_name && symbol_name[0] == '.') { - llvm::StringRef symbol_name_ref(symbol_name); - static const llvm::StringRef g_objc_v1_prefix_class( - ".objc_class_name_"); - if (symbol_name_ref.startswith(g_objc_v1_prefix_class)) { - symbol_name_non_abi_mangled = symbol_name; - symbol_name = symbol_name + g_objc_v1_prefix_class.size(); - type = eSymbolTypeObjCClass; - demangled_is_synthesized = true; - } - } - } - } - } - } break; - } - } - - if (add_nlist) { - uint64_t symbol_value = nlist.n_value; - - if (symbol_name_non_abi_mangled) { - sym[sym_idx].GetMangled().SetMangledName( - ConstString(symbol_name_non_abi_mangled)); - sym[sym_idx].GetMangled().SetDemangledName( - ConstString(symbol_name)); - } else { - bool symbol_name_is_mangled = false; - - if (symbol_name && symbol_name[0] == '_') { - symbol_name_is_mangled = symbol_name[1] == '_'; - symbol_name++; // Skip the leading underscore - } - - if (symbol_name) { - ConstString const_symbol_name(symbol_name); - sym[sym_idx].GetMangled().SetValue(const_symbol_name, - symbol_name_is_mangled); - } - } - - if (is_gsym) { - const char *gsym_name = sym[sym_idx] - .GetMangled() - .GetName(lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) - .GetCString(); - if (gsym_name) - N_GSYM_name_to_sym_idx[gsym_name] = sym_idx; - } - - if (symbol_section) { - const addr_t section_file_addr = symbol_section->GetFileAddress(); - if (symbol_byte_size == 0 && function_starts_count > 0) { - addr_t symbol_lookup_file_addr = nlist.n_value; - // Do an exact address match for non-ARM addresses, else get the - // closest since the symbol might be a thumb symbol which has an - // address with bit zero set - FunctionStarts::Entry *func_start_entry = - function_starts.FindEntry(symbol_lookup_file_addr, !is_arm); - if (is_arm && func_start_entry) { - // Verify that the function start address is the symbol address - // (ARM) or the symbol address + 1 (thumb) - if (func_start_entry->addr != symbol_lookup_file_addr && - func_start_entry->addr != (symbol_lookup_file_addr + 1)) { - // Not the right entry, NULL it out... - func_start_entry = NULL; - } - } - if (func_start_entry) { - func_start_entry->data = true; - - addr_t symbol_file_addr = func_start_entry->addr; - if (is_arm) - symbol_file_addr &= THUMB_ADDRESS_BIT_MASK; - - const FunctionStarts::Entry *next_func_start_entry = - function_starts.FindNextEntry(func_start_entry); - const addr_t section_end_file_addr = - section_file_addr + symbol_section->GetByteSize(); - if (next_func_start_entry) { - addr_t next_symbol_file_addr = next_func_start_entry->addr; - // Be sure the clear the Thumb address bit when we calculate - // the size from the current and next address - if (is_arm) - next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK; - symbol_byte_size = std::min<lldb::addr_t>( - next_symbol_file_addr - symbol_file_addr, - section_end_file_addr - symbol_file_addr); - } else { - symbol_byte_size = section_end_file_addr - symbol_file_addr; - } - } - } - symbol_value -= section_file_addr; - } - - if (!is_debug) { - if (type == eSymbolTypeCode) { - // See if we can find a N_FUN entry for any code symbols. If we - // do find a match, and the name matches, then we can merge the - // two into just the function symbol to avoid duplicate entries - // in the symbol table - std::pair<ValueToSymbolIndexMap::const_iterator, - ValueToSymbolIndexMap::const_iterator> - range; - range = N_FUN_addr_to_sym_idx.equal_range(nlist.n_value); - if (range.first != range.second) { - bool found_it = false; - for (ValueToSymbolIndexMap::const_iterator pos = range.first; - pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) == - sym[pos->second].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled)) { - m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; - // We just need the flags from the linker symbol, so put - // these flags into the N_FUN flags to avoid duplicate - // symbols in the symbol table - sym[pos->second].SetExternal(sym[sym_idx].IsExternal()); - sym[pos->second].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - if (resolver_addresses.find(nlist.n_value) != - resolver_addresses.end()) - sym[pos->second].SetType(eSymbolTypeResolver); - sym[sym_idx].Clear(); - found_it = true; - break; - } - } - if (found_it) - continue; - } else { - if (resolver_addresses.find(nlist.n_value) != - resolver_addresses.end()) - type = eSymbolTypeResolver; - } - } else if (type == eSymbolTypeData || - type == eSymbolTypeObjCClass || - type == eSymbolTypeObjCMetaClass || - type == eSymbolTypeObjCIVar) { - // See if we can find a N_STSYM entry for any data symbols. If we - // do find a match, and the name matches, then we can merge the - // two into just the Static symbol to avoid duplicate entries in - // the symbol table - std::pair<ValueToSymbolIndexMap::const_iterator, - ValueToSymbolIndexMap::const_iterator> - range; - range = N_STSYM_addr_to_sym_idx.equal_range(nlist.n_value); - if (range.first != range.second) { - bool found_it = false; - for (ValueToSymbolIndexMap::const_iterator pos = range.first; - pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) == - sym[pos->second].GetMangled().GetName( - lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled)) { - m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; - // We just need the flags from the linker symbol, so put - // these flags into the N_STSYM flags to avoid duplicate - // symbols in the symbol table - sym[pos->second].SetExternal(sym[sym_idx].IsExternal()); - sym[pos->second].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - sym[sym_idx].Clear(); - found_it = true; - break; - } - } - if (found_it) - continue; - } else { - // Combine N_GSYM stab entries with the non stab symbol - const char *gsym_name = sym[sym_idx] - .GetMangled() - .GetName(lldb::eLanguageTypeUnknown, - Mangled::ePreferMangled) - .GetCString(); - if (gsym_name) { - ConstNameToSymbolIndexMap::const_iterator pos = - N_GSYM_name_to_sym_idx.find(gsym_name); - if (pos != N_GSYM_name_to_sym_idx.end()) { - const uint32_t GSYM_sym_idx = pos->second; - m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx; - // Copy the address, because often the N_GSYM address has - // an invalid address of zero when the global is a common - // symbol - sym[GSYM_sym_idx].GetAddressRef().SetSection( - symbol_section); - sym[GSYM_sym_idx].GetAddressRef().SetOffset(symbol_value); - // We just need the flags from the linker symbol, so put - // these flags into the N_GSYM flags to avoid duplicate - // symbols in the symbol table - sym[GSYM_sym_idx].SetFlags(nlist.n_type << 16 | - nlist.n_desc); - sym[sym_idx].Clear(); - continue; - } - } - } - } - } - - sym[sym_idx].SetID(nlist_idx); - sym[sym_idx].SetType(type); - if (set_value) { - sym[sym_idx].GetAddressRef().SetSection(symbol_section); - sym[sym_idx].GetAddressRef().SetOffset(symbol_value); - } - sym[sym_idx].SetFlags(nlist.n_type << 16 | nlist.n_desc); - - if (symbol_byte_size > 0) - sym[sym_idx].SetByteSize(symbol_byte_size); - - if (demangled_is_synthesized) - sym[sym_idx].SetDemangledNameIsSynthesized(true); - - ++sym_idx; - } else { - sym[sym_idx].Clear(); - } - } - - for (const auto &pos : reexport_shlib_needs_fixup) { - const auto undef_pos = undefined_name_to_desc.find(pos.second); - if (undef_pos != undefined_name_to_desc.end()) { - const uint8_t dylib_ordinal = - llvm::MachO::GET_LIBRARY_ORDINAL(undef_pos->second); - if (dylib_ordinal > 0 && dylib_ordinal < dylib_files.GetSize()) - sym[pos.first].SetReExportedSymbolSharedLibrary( - dylib_files.GetFileSpecAtIndex(dylib_ordinal - 1)); - } - } - } - - uint32_t synthetic_sym_id = symtab_load_command.nsyms; - - if (function_starts_count > 0) { - uint32_t num_synthetic_function_symbols = 0; - for (i = 0; i < function_starts_count; ++i) { - if (!function_starts.GetEntryRef(i).data) - ++num_synthetic_function_symbols; - } - - if (num_synthetic_function_symbols > 0) { - if (num_syms < sym_idx + num_synthetic_function_symbols) { - num_syms = sym_idx + num_synthetic_function_symbols; - sym = symtab->Resize(num_syms); - } - for (i = 0; i < function_starts_count; ++i) { - const FunctionStarts::Entry *func_start_entry = - function_starts.GetEntryAtIndex(i); - if (!func_start_entry->data) { - addr_t symbol_file_addr = func_start_entry->addr; - uint32_t symbol_flags = 0; - if (is_arm) { - if (symbol_file_addr & 1) - symbol_flags = MACHO_NLIST_ARM_SYMBOL_IS_THUMB; - symbol_file_addr &= THUMB_ADDRESS_BIT_MASK; - } - Address symbol_addr; - if (module_sp->ResolveFileAddress(symbol_file_addr, symbol_addr)) { - SectionSP symbol_section(symbol_addr.GetSection()); - uint32_t symbol_byte_size = 0; - if (symbol_section) { - const addr_t section_file_addr = - symbol_section->GetFileAddress(); - const FunctionStarts::Entry *next_func_start_entry = - function_starts.FindNextEntry(func_start_entry); - const addr_t section_end_file_addr = - section_file_addr + symbol_section->GetByteSize(); - if (next_func_start_entry) { - addr_t next_symbol_file_addr = next_func_start_entry->addr; - if (is_arm) - next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK; - symbol_byte_size = std::min<lldb::addr_t>( - next_symbol_file_addr - symbol_file_addr, - section_end_file_addr - symbol_file_addr); - } else { - symbol_byte_size = section_end_file_addr - symbol_file_addr; - } - sym[sym_idx].SetID(synthetic_sym_id++); - sym[sym_idx].GetMangled().SetDemangledName( - GetNextSyntheticSymbolName()); - sym[sym_idx].SetType(eSymbolTypeCode); - sym[sym_idx].SetIsSynthetic(true); - sym[sym_idx].GetAddressRef() = symbol_addr; - if (symbol_flags) - sym[sym_idx].SetFlags(symbol_flags); - if (symbol_byte_size) - sym[sym_idx].SetByteSize(symbol_byte_size); - ++sym_idx; - } - } - } - } - } - } - - // Trim our symbols down to just what we ended up with after removing any - // symbols. - if (sym_idx < num_syms) { - num_syms = sym_idx; - sym = symtab->Resize(num_syms); - } - - // Now synthesize indirect symbols - if (m_dysymtab.nindirectsyms != 0) { - if (indirect_symbol_index_data.GetByteSize()) { - NListIndexToSymbolIndexMap::const_iterator end_index_pos = - m_nlist_idx_to_sym_idx.end(); - - for (uint32_t sect_idx = 1; sect_idx < m_mach_sections.size(); - ++sect_idx) { - if ((m_mach_sections[sect_idx].flags & SECTION_TYPE) == - S_SYMBOL_STUBS) { - uint32_t symbol_stub_byte_size = - m_mach_sections[sect_idx].reserved2; - if (symbol_stub_byte_size == 0) - continue; - - const uint32_t num_symbol_stubs = - m_mach_sections[sect_idx].size / symbol_stub_byte_size; - - if (num_symbol_stubs == 0) - continue; - - const uint32_t symbol_stub_index_offset = - m_mach_sections[sect_idx].reserved1; - for (uint32_t stub_idx = 0; stub_idx < num_symbol_stubs; - ++stub_idx) { - const uint32_t symbol_stub_index = - symbol_stub_index_offset + stub_idx; - const lldb::addr_t symbol_stub_addr = - m_mach_sections[sect_idx].addr + - (stub_idx * symbol_stub_byte_size); - lldb::offset_t symbol_stub_offset = symbol_stub_index * 4; - if (indirect_symbol_index_data.ValidOffsetForDataOfSize( - symbol_stub_offset, 4)) { - const uint32_t stub_sym_id = - indirect_symbol_index_data.GetU32(&symbol_stub_offset); - if (stub_sym_id & (INDIRECT_SYMBOL_ABS | INDIRECT_SYMBOL_LOCAL)) - continue; - - NListIndexToSymbolIndexMap::const_iterator index_pos = - m_nlist_idx_to_sym_idx.find(stub_sym_id); - Symbol *stub_symbol = NULL; - if (index_pos != end_index_pos) { - // We have a remapping from the original nlist index to a - // current symbol index, so just look this up by index - stub_symbol = symtab->SymbolAtIndex(index_pos->second); - } else { - // We need to lookup a symbol using the original nlist symbol - // index since this index is coming from the S_SYMBOL_STUBS - stub_symbol = symtab->FindSymbolByID(stub_sym_id); - } - - if (stub_symbol) { - Address so_addr(symbol_stub_addr, section_list); - - if (stub_symbol->GetType() == eSymbolTypeUndefined) { - // Change the external symbol into a trampoline that makes - // sense These symbols were N_UNDF N_EXT, and are useless - // to us, so we can re-use them so we don't have to make up - // a synthetic symbol for no good reason. - if (resolver_addresses.find(symbol_stub_addr) == - resolver_addresses.end()) - stub_symbol->SetType(eSymbolTypeTrampoline); - else - stub_symbol->SetType(eSymbolTypeResolver); - stub_symbol->SetExternal(false); - stub_symbol->GetAddressRef() = so_addr; - stub_symbol->SetByteSize(symbol_stub_byte_size); - } else { - // Make a synthetic symbol to describe the trampoline stub - Mangled stub_symbol_mangled_name(stub_symbol->GetMangled()); - if (sym_idx >= num_syms) { - sym = symtab->Resize(++num_syms); - stub_symbol = NULL; // this pointer no longer valid - } - sym[sym_idx].SetID(synthetic_sym_id++); - sym[sym_idx].GetMangled() = stub_symbol_mangled_name; - if (resolver_addresses.find(symbol_stub_addr) == - resolver_addresses.end()) - sym[sym_idx].SetType(eSymbolTypeTrampoline); - else - sym[sym_idx].SetType(eSymbolTypeResolver); - sym[sym_idx].SetIsSynthetic(true); - sym[sym_idx].GetAddressRef() = so_addr; - sym[sym_idx].SetByteSize(symbol_stub_byte_size); - ++sym_idx; - } - } else { - if (log) - log->Warning("symbol stub referencing symbol table symbol " - "%u that isn't in our minimal symbol table, " - "fix this!!!", - stub_sym_id); - } - } - } - } - } - } - } - - if (!trie_entries.empty()) { - for (const auto &e : trie_entries) { - if (e.entry.import_name) { - // Only add indirect symbols from the Trie entries if we didn't have - // a N_INDR nlist entry for this already - if (indirect_symbol_names.find(e.entry.name) == - indirect_symbol_names.end()) { - // Make a synthetic symbol to describe re-exported symbol. - if (sym_idx >= num_syms) - sym = symtab->Resize(++num_syms); - sym[sym_idx].SetID(synthetic_sym_id++); - sym[sym_idx].GetMangled() = Mangled(e.entry.name); - sym[sym_idx].SetType(eSymbolTypeReExported); - sym[sym_idx].SetIsSynthetic(true); - sym[sym_idx].SetReExportedSymbolName(e.entry.import_name); - if (e.entry.other > 0 && e.entry.other <= dylib_files.GetSize()) { - sym[sym_idx].SetReExportedSymbolSharedLibrary( - dylib_files.GetFileSpecAtIndex(e.entry.other - 1)); - } - ++sym_idx; - } - } - } - } - - // StreamFile s(stdout, false); - // s.Printf ("Symbol table before CalculateSymbolSizes():\n"); - // symtab->Dump(&s, NULL, eSortOrderNone); - // Set symbol byte sizes correctly since mach-o nlist entries don't have - // sizes - symtab->CalculateSymbolSizes(); - - // s.Printf ("Symbol table after CalculateSymbolSizes():\n"); - // symtab->Dump(&s, NULL, eSortOrderNone); - - return symtab->GetNumSymbols(); - } - return 0; -} - -void ObjectFileMachO::Dump(Stream *s) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - s->Printf("%p: ", static_cast<void *>(this)); - s->Indent(); - if (m_header.magic == MH_MAGIC_64 || m_header.magic == MH_CIGAM_64) - s->PutCString("ObjectFileMachO64"); - else - s->PutCString("ObjectFileMachO32"); - - ArchSpec header_arch = GetArchitecture(); - - *s << ", file = '" << m_file - << "', triple = " << header_arch.GetTriple().getTriple() << "\n"; - - SectionList *sections = GetSectionList(); - if (sections) - sections->Dump(s, NULL, true, UINT32_MAX); - - if (m_symtab_ap.get()) - m_symtab_ap->Dump(s, NULL, eSortOrderNone); - } -} - -bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header, - const lldb_private::DataExtractor &data, - lldb::offset_t lc_offset, - lldb_private::UUID &uuid) { - uint32_t i; - struct uuid_command load_cmd; - - lldb::offset_t offset = lc_offset; - for (i = 0; i < header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - if (load_cmd.cmd == LC_UUID) { - const uint8_t *uuid_bytes = data.PeekData(offset, 16); - - if (uuid_bytes) { - // OpenCL on Mac OS X uses the same UUID for each of its object files. - // We pretend these object files have no UUID to prevent crashing. - - const uint8_t opencl_uuid[] = {0x8c, 0x8e, 0xb3, 0x9b, 0x3b, 0xa8, - 0x4b, 0x16, 0xb6, 0xa4, 0x27, 0x63, - 0xbb, 0x14, 0xf0, 0x0d}; - - if (!memcmp(uuid_bytes, opencl_uuid, 16)) - return false; - - uuid = UUID::fromOptionalData(uuid_bytes, 16); - return true; - } - return false; - } - offset = cmd_offset + load_cmd.cmdsize; - } - return false; -} - -static llvm::StringRef GetOSName(uint32_t cmd) { - switch (cmd) { - case llvm::MachO::LC_VERSION_MIN_IPHONEOS: - return llvm::Triple::getOSTypeName(llvm::Triple::IOS); - case llvm::MachO::LC_VERSION_MIN_MACOSX: - return llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); - case llvm::MachO::LC_VERSION_MIN_TVOS: - return llvm::Triple::getOSTypeName(llvm::Triple::TvOS); - case llvm::MachO::LC_VERSION_MIN_WATCHOS: - return llvm::Triple::getOSTypeName(llvm::Triple::WatchOS); - default: - llvm_unreachable("unexpected LC_VERSION load command"); - } -} - -namespace { - struct OSEnv { - llvm::StringRef os_type; - llvm::StringRef environment; - OSEnv(uint32_t cmd) { - switch (cmd) { - case PLATFORM_MACOS: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::MacOSX); - return; - case PLATFORM_IOS: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS); - return; - case PLATFORM_TVOS: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS); - return; - case PLATFORM_WATCHOS: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS); - return; -// NEED_BRIDGEOS_TRIPLE case PLATFORM_BRIDGEOS: -// NEED_BRIDGEOS_TRIPLE os_type = llvm::Triple::getOSTypeName(llvm::Triple::BridgeOS); -// NEED_BRIDGEOS_TRIPLE return; -#if defined (PLATFORM_IOSSIMULATOR) && defined (PLATFORM_TVOSSIMULATOR) && defined (PLATFORM_WATCHOSSIMULATOR) - case PLATFORM_IOSSIMULATOR: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS); - environment = - llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator); - return; - case PLATFORM_TVOSSIMULATOR: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS); - environment = - llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator); - return; - case PLATFORM_WATCHOSSIMULATOR: - os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS); - environment = - llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator); - return; -#endif - default: { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | - LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("unsupported platform in LC_BUILD_VERSION"); - } - } - } - }; - - struct MinOS { - uint32_t major_version, minor_version, patch_version; - MinOS(uint32_t version) - : major_version(version >> 16), - minor_version((version >> 8) & 0xffu), - patch_version(version & 0xffu) {} - }; -} // namespace - -ArchSpec -ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header, - const lldb_private::DataExtractor &data, - lldb::offset_t lc_offset) { - ArchSpec arch; - arch.SetArchitecture(eArchTypeMachO, header.cputype, header.cpusubtype); - - if (arch.IsValid()) { - llvm::Triple &triple = arch.GetTriple(); - - // Set OS to an unspecified unknown or a "*" so it can match any OS - triple.setOS(llvm::Triple::UnknownOS); - triple.setOSName(llvm::StringRef()); - - if (header.filetype == MH_PRELOAD) { - if (header.cputype == CPU_TYPE_ARM) { - // If this is a 32-bit arm binary, and it's a standalone binary, force - // the Vendor to Apple so we don't accidentally pick up the generic - // armv7 ABI at runtime. Apple's armv7 ABI always uses r7 for the - // frame pointer register; most other armv7 ABIs use a combination of - // r7 and r11. - triple.setVendor(llvm::Triple::Apple); - } else { - // Set vendor to an unspecified unknown or a "*" so it can match any - // vendor This is required for correct behavior of EFI debugging on - // x86_64 - triple.setVendor(llvm::Triple::UnknownVendor); - triple.setVendorName(llvm::StringRef()); - } - return arch; - } else { - struct load_command load_cmd; - llvm::SmallString<16> os_name; - llvm::raw_svector_ostream os(os_name); - - // See if there is an LC_VERSION_MIN_* load command that can give - // us the OS type. - lldb::offset_t offset = lc_offset; - for (uint32_t i = 0; i < header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - struct version_min_command version_min; - switch (load_cmd.cmd) { - case llvm::MachO::LC_VERSION_MIN_IPHONEOS: - case llvm::MachO::LC_VERSION_MIN_MACOSX: - case llvm::MachO::LC_VERSION_MIN_TVOS: - case llvm::MachO::LC_VERSION_MIN_WATCHOS: { - if (load_cmd.cmdsize != sizeof(version_min)) - break; - if (data.ExtractBytes(cmd_offset, sizeof(version_min), - data.GetByteOrder(), &version_min) == 0) - break; - MinOS min_os(version_min.version); - os << GetOSName(load_cmd.cmd) << min_os.major_version << '.' - << min_os.minor_version << '.' << min_os.patch_version; - triple.setOSName(os.str()); - return arch; - } - default: - break; - } - - offset = cmd_offset + load_cmd.cmdsize; - } - - // See if there is an LC_BUILD_VERSION load command that can give - // us the OS type. - - offset = lc_offset; - for (uint32_t i = 0; i < header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - if (data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - do { - if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) { - struct build_version_command build_version; - if (load_cmd.cmdsize < sizeof(build_version)) { - // Malformed load command. - break; - } - if (data.ExtractBytes(cmd_offset, sizeof(build_version), - data.GetByteOrder(), &build_version) == 0) - break; - MinOS min_os(build_version.minos); - OSEnv os_env(build_version.platform); - if (os_env.os_type.empty()) - break; - os << os_env.os_type << min_os.major_version << '.' - << min_os.minor_version << '.' << min_os.patch_version; - triple.setOSName(os.str()); - if (!os_env.environment.empty()) - triple.setEnvironmentName(os_env.environment); - return arch; - } - } while (0); - offset = cmd_offset + load_cmd.cmdsize; - } - - if (header.filetype != MH_KEXT_BUNDLE) { - // We didn't find a LC_VERSION_MIN load command and this isn't a KEXT - // so lets not say our Vendor is Apple, leave it as an unspecified - // unknown - triple.setVendor(llvm::Triple::UnknownVendor); - triple.setVendorName(llvm::StringRef()); - } - } - } - return arch; -} - -bool ObjectFileMachO::GetUUID(lldb_private::UUID *uuid) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - return GetUUID(m_header, m_data, offset, *uuid); - } - return false; -} - -uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) { - uint32_t count = 0; - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - struct load_command load_cmd; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - std::vector<std::string> rpath_paths; - std::vector<std::string> rpath_relative_paths; - std::vector<std::string> at_exec_relative_paths; - uint32_t i; - for (i = 0; i < m_header.ncmds; ++i) { - const uint32_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - switch (load_cmd.cmd) { - case LC_RPATH: - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LOAD_DYLINKER: - case LC_LOADFVMLIB: - case LC_LOAD_UPWARD_DYLIB: { - uint32_t name_offset = cmd_offset + m_data.GetU32(&offset); - const char *path = m_data.PeekCStr(name_offset); - if (path) { - if (load_cmd.cmd == LC_RPATH) - rpath_paths.push_back(path); - else { - if (path[0] == '@') { - if (strncmp(path, "@rpath", strlen("@rpath")) == 0) - rpath_relative_paths.push_back(path + strlen("@rpath")); - else if (strncmp(path, "@executable_path", - strlen("@executable_path")) == 0) - at_exec_relative_paths.push_back(path - + strlen("@executable_path")); - } else { - FileSpec file_spec(path); - if (files.AppendIfUnique(file_spec)) - count++; - } - } - } - } break; - - default: - break; - } - offset = cmd_offset + load_cmd.cmdsize; - } - - FileSpec this_file_spec(m_file); - FileSystem::Instance().Resolve(this_file_spec); - - if (!rpath_paths.empty()) { - // Fixup all LC_RPATH values to be absolute paths - std::string loader_path("@loader_path"); - std::string executable_path("@executable_path"); - for (auto &rpath : rpath_paths) { - if (rpath.find(loader_path) == 0) { - rpath.erase(0, loader_path.size()); - rpath.insert(0, this_file_spec.GetDirectory().GetCString()); - } else if (rpath.find(executable_path) == 0) { - rpath.erase(0, executable_path.size()); - rpath.insert(0, this_file_spec.GetDirectory().GetCString()); - } - } - - for (const auto &rpath_relative_path : rpath_relative_paths) { - for (const auto &rpath : rpath_paths) { - std::string path = rpath; - path += rpath_relative_path; - // It is OK to resolve this path because we must find a file on disk - // for us to accept it anyway if it is rpath relative. - FileSpec file_spec(path); - FileSystem::Instance().Resolve(file_spec); - if (FileSystem::Instance().Exists(file_spec) && - files.AppendIfUnique(file_spec)) { - count++; - break; - } - } - } - } - - // We may have @executable_paths but no RPATHS. Figure those out here. - // Only do this if this object file is the executable. We have no way to - // get back to the actual executable otherwise, so we won't get the right - // path. - if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) { - FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent(); - for (const auto &at_exec_relative_path : at_exec_relative_paths) { - FileSpec file_spec = - exec_dir.CopyByAppendingPathComponent(at_exec_relative_path); - if (FileSystem::Instance().Exists(file_spec) && - files.AppendIfUnique(file_spec)) - count++; - } - } - } - return count; -} - -lldb_private::Address ObjectFileMachO::GetEntryPointAddress() { - // If the object file is not an executable it can't hold the entry point. - // m_entry_point_address is initialized to an invalid address, so we can just - // return that. If m_entry_point_address is valid it means we've found it - // already, so return the cached value. - - if (!IsExecutable() || m_entry_point_address.IsValid()) - return m_entry_point_address; - - // Otherwise, look for the UnixThread or Thread command. The data for the - // Thread command is given in /usr/include/mach-o.h, but it is basically: - // - // uint32_t flavor - this is the flavor argument you would pass to - // thread_get_state - // uint32_t count - this is the count of longs in the thread state data - // struct XXX_thread_state state - this is the structure from - // <machine/thread_status.h> corresponding to the flavor. - // <repeat this trio> - // - // So we just keep reading the various register flavors till we find the GPR - // one, then read the PC out of there. - // FIXME: We will need to have a "RegisterContext data provider" class at some - // point that can get all the registers - // out of data in this form & attach them to a given thread. That should - // underlie the MacOS X User process plugin, and we'll also need it for the - // MacOS X Core File process plugin. When we have that we can also use it - // here. - // - // For now we hard-code the offsets and flavors we need: - // - // - - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - struct load_command load_cmd; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - uint32_t i; - lldb::addr_t start_address = LLDB_INVALID_ADDRESS; - bool done = false; - - for (i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - switch (load_cmd.cmd) { - case LC_UNIXTHREAD: - case LC_THREAD: { - while (offset < cmd_offset + load_cmd.cmdsize) { - uint32_t flavor = m_data.GetU32(&offset); - uint32_t count = m_data.GetU32(&offset); - if (count == 0) { - // We've gotten off somehow, log and exit; - return m_entry_point_address; - } - - switch (m_header.cputype) { - case llvm::MachO::CPU_TYPE_ARM: - if (flavor == 1 || - flavor == 9) // ARM_THREAD_STATE/ARM_THREAD_STATE32 from - // mach/arm/thread_status.h - { - offset += 60; // This is the offset of pc in the GPR thread state - // data structure. - start_address = m_data.GetU32(&offset); - done = true; - } - break; - case llvm::MachO::CPU_TYPE_ARM64: - if (flavor == 6) // ARM_THREAD_STATE64 from mach/arm/thread_status.h - { - offset += 256; // This is the offset of pc in the GPR thread state - // data structure. - start_address = m_data.GetU64(&offset); - done = true; - } - break; - case llvm::MachO::CPU_TYPE_I386: - if (flavor == - 1) // x86_THREAD_STATE32 from mach/i386/thread_status.h - { - offset += 40; // This is the offset of eip in the GPR thread state - // data structure. - start_address = m_data.GetU32(&offset); - done = true; - } - break; - case llvm::MachO::CPU_TYPE_X86_64: - if (flavor == - 4) // x86_THREAD_STATE64 from mach/i386/thread_status.h - { - offset += 16 * 8; // This is the offset of rip in the GPR thread - // state data structure. - start_address = m_data.GetU64(&offset); - done = true; - } - break; - default: - return m_entry_point_address; - } - // Haven't found the GPR flavor yet, skip over the data for this - // flavor: - if (done) - break; - offset += count * 4; - } - } break; - case LC_MAIN: { - ConstString text_segment_name("__TEXT"); - uint64_t entryoffset = m_data.GetU64(&offset); - SectionSP text_segment_sp = - GetSectionList()->FindSectionByName(text_segment_name); - if (text_segment_sp) { - done = true; - start_address = text_segment_sp->GetFileAddress() + entryoffset; - } - } break; - - default: - break; - } - if (done) - break; - - // Go to the next load command: - offset = cmd_offset + load_cmd.cmdsize; - } - - if (start_address != LLDB_INVALID_ADDRESS) { - // We got the start address from the load commands, so now resolve that - // address in the sections of this ObjectFile: - if (!m_entry_point_address.ResolveAddressUsingFileSections( - start_address, GetSectionList())) { - m_entry_point_address.Clear(); - } - } else { - // We couldn't read the UnixThread load command - maybe it wasn't there. - // As a fallback look for the "start" symbol in the main executable. - - ModuleSP module_sp(GetModule()); - - if (module_sp) { - SymbolContextList contexts; - SymbolContext context; - if (module_sp->FindSymbolsWithNameAndType(ConstString("start"), - eSymbolTypeCode, contexts)) { - if (contexts.GetContextAtIndex(0, context)) - m_entry_point_address = context.symbol->GetAddress(); - } - } - } - } - - return m_entry_point_address; -} - -lldb_private::Address ObjectFileMachO::GetBaseAddress() { - lldb_private::Address header_addr; - SectionList *section_list = GetSectionList(); - if (section_list) { - SectionSP text_segment_sp( - section_list->FindSectionByName(GetSegmentNameTEXT())); - if (text_segment_sp) { - header_addr.SetSection(text_segment_sp); - header_addr.SetOffset(0); - } - } - return header_addr; -} - -uint32_t ObjectFileMachO::GetNumThreadContexts() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (!m_thread_context_offsets_valid) { - m_thread_context_offsets_valid = true; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - FileRangeArray::Entry file_range; - thread_command thread_cmd; - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const uint32_t cmd_offset = offset; - if (m_data.GetU32(&offset, &thread_cmd, 2) == NULL) - break; - - if (thread_cmd.cmd == LC_THREAD) { - file_range.SetRangeBase(offset); - file_range.SetByteSize(thread_cmd.cmdsize - 8); - m_thread_context_offsets.Append(file_range); - } - offset = cmd_offset + thread_cmd.cmdsize; - } - } - } - return m_thread_context_offsets.GetSize(); -} - -std::string ObjectFileMachO::GetIdentifierString() { - std::string result; - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - // First, look over the load commands for an LC_NOTE load command with - // data_owner string "kern ver str" & use that if found. - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const uint32_t cmd_offset = offset; - load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == LC_NOTE) - { - char data_owner[17]; - m_data.CopyData (offset, 16, data_owner); - data_owner[16] = '\0'; - offset += 16; - uint64_t fileoff = m_data.GetU64_unchecked (&offset); - uint64_t size = m_data.GetU64_unchecked (&offset); - - // "kern ver str" has a uint32_t version and then a nul terminated - // c-string. - if (strcmp ("kern ver str", data_owner) == 0) - { - offset = fileoff; - uint32_t version; - if (m_data.GetU32 (&offset, &version, 1) != nullptr) - { - if (version == 1) - { - uint32_t strsize = size - sizeof (uint32_t); - char *buf = (char*) malloc (strsize); - if (buf) - { - m_data.CopyData (offset, strsize, buf); - buf[strsize - 1] = '\0'; - result = buf; - if (buf) - free (buf); - return result; - } - } - } - } - } - offset = cmd_offset + lc.cmdsize; - } - - // Second, make a pass over the load commands looking for an obsolete - // LC_IDENT load command. - offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const uint32_t cmd_offset = offset; - struct ident_command ident_command; - if (m_data.GetU32(&offset, &ident_command, 2) == NULL) - break; - if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) { - char *buf = (char *) malloc (ident_command.cmdsize); - if (buf != nullptr - && m_data.CopyData (offset, ident_command.cmdsize, buf) == ident_command.cmdsize) { - buf[ident_command.cmdsize - 1] = '\0'; - result = buf; - } - if (buf) - free (buf); - } - offset = cmd_offset + ident_command.cmdsize; - } - - } - return result; -} - -bool ObjectFileMachO::GetCorefileMainBinaryInfo (addr_t &address, UUID &uuid) { - address = LLDB_INVALID_ADDRESS; - uuid.Clear(); - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const uint32_t cmd_offset = offset; - load_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == LC_NOTE) - { - char data_owner[17]; - memset (data_owner, 0, sizeof (data_owner)); - m_data.CopyData (offset, 16, data_owner); - offset += 16; - uint64_t fileoff = m_data.GetU64_unchecked (&offset); - uint64_t size = m_data.GetU64_unchecked (&offset); - - // "main bin spec" (main binary specification) data payload is - // formatted: - // uint32_t version [currently 1] - // uint32_t type [0 == unspecified, 1 == kernel, 2 == user process] - // uint64_t address [ UINT64_MAX if address not specified ] - // uuid_t uuid [ all zero's if uuid not specified ] - // uint32_t log2_pagesize [ process page size in log base 2, e.g. 4k pages are 12. 0 for unspecified ] - - if (strcmp ("main bin spec", data_owner) == 0 && size >= 32) - { - offset = fileoff; - uint32_t version; - if (m_data.GetU32 (&offset, &version, 1) != nullptr && version == 1) - { - uint32_t type = 0; - uuid_t raw_uuid; - memset (raw_uuid, 0, sizeof (uuid_t)); - - if (m_data.GetU32(&offset, &type, 1) && - m_data.GetU64(&offset, &address, 1) && - m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) { - uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t)); - return true; - } - } - } - } - offset = cmd_offset + lc.cmdsize; - } - } - return false; -} - -lldb::RegisterContextSP -ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx, - lldb_private::Thread &thread) { - lldb::RegisterContextSP reg_ctx_sp; - - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (!m_thread_context_offsets_valid) - GetNumThreadContexts(); - - const FileRangeArray::Entry *thread_context_file_range = - m_thread_context_offsets.GetEntryAtIndex(idx); - if (thread_context_file_range) { - - DataExtractor data(m_data, thread_context_file_range->GetRangeBase(), - thread_context_file_range->GetByteSize()); - - switch (m_header.cputype) { - case llvm::MachO::CPU_TYPE_ARM64: - reg_ctx_sp.reset(new RegisterContextDarwin_arm64_Mach(thread, data)); - break; - - case llvm::MachO::CPU_TYPE_ARM: - reg_ctx_sp.reset(new RegisterContextDarwin_arm_Mach(thread, data)); - break; - - case llvm::MachO::CPU_TYPE_I386: - reg_ctx_sp.reset(new RegisterContextDarwin_i386_Mach(thread, data)); - break; - - case llvm::MachO::CPU_TYPE_X86_64: - reg_ctx_sp.reset(new RegisterContextDarwin_x86_64_Mach(thread, data)); - break; - } - } - } - return reg_ctx_sp; -} - -ObjectFile::Type ObjectFileMachO::CalculateType() { - switch (m_header.filetype) { - case MH_OBJECT: // 0x1u - if (GetAddressByteSize() == 4) { - // 32 bit kexts are just object files, but they do have a valid - // UUID load command. - UUID uuid; - if (GetUUID(&uuid)) { - // this checking for the UUID load command is not enough we could - // eventually look for the symbol named "OSKextGetCurrentIdentifier" as - // this is required of kexts - if (m_strata == eStrataInvalid) - m_strata = eStrataKernel; - return eTypeSharedLibrary; - } - } - return eTypeObjectFile; - - case MH_EXECUTE: - return eTypeExecutable; // 0x2u - case MH_FVMLIB: - return eTypeSharedLibrary; // 0x3u - case MH_CORE: - return eTypeCoreFile; // 0x4u - case MH_PRELOAD: - return eTypeSharedLibrary; // 0x5u - case MH_DYLIB: - return eTypeSharedLibrary; // 0x6u - case MH_DYLINKER: - return eTypeDynamicLinker; // 0x7u - case MH_BUNDLE: - return eTypeSharedLibrary; // 0x8u - case MH_DYLIB_STUB: - return eTypeStubLibrary; // 0x9u - case MH_DSYM: - return eTypeDebugInfo; // 0xAu - case MH_KEXT_BUNDLE: - return eTypeSharedLibrary; // 0xBu - default: - break; - } - return eTypeUnknown; -} - -ObjectFile::Strata ObjectFileMachO::CalculateStrata() { - switch (m_header.filetype) { - case MH_OBJECT: // 0x1u - { - // 32 bit kexts are just object files, but they do have a valid - // UUID load command. - UUID uuid; - if (GetUUID(&uuid)) { - // this checking for the UUID load command is not enough we could - // eventually look for the symbol named "OSKextGetCurrentIdentifier" as - // this is required of kexts - if (m_type == eTypeInvalid) - m_type = eTypeSharedLibrary; - - return eStrataKernel; - } - } - return eStrataUnknown; - - case MH_EXECUTE: // 0x2u - // Check for the MH_DYLDLINK bit in the flags - if (m_header.flags & MH_DYLDLINK) { - return eStrataUser; - } else { - SectionList *section_list = GetSectionList(); - if (section_list) { - static ConstString g_kld_section_name("__KLD"); - if (section_list->FindSectionByName(g_kld_section_name)) - return eStrataKernel; - } - } - return eStrataRawImage; - - case MH_FVMLIB: - return eStrataUser; // 0x3u - case MH_CORE: - return eStrataUnknown; // 0x4u - case MH_PRELOAD: - return eStrataRawImage; // 0x5u - case MH_DYLIB: - return eStrataUser; // 0x6u - case MH_DYLINKER: - return eStrataUser; // 0x7u - case MH_BUNDLE: - return eStrataUser; // 0x8u - case MH_DYLIB_STUB: - return eStrataUser; // 0x9u - case MH_DSYM: - return eStrataUnknown; // 0xAu - case MH_KEXT_BUNDLE: - return eStrataKernel; // 0xBu - default: - break; - } - return eStrataUnknown; -} - -llvm::VersionTuple ObjectFileMachO::GetVersion() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - struct dylib_command load_cmd; - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - uint32_t version_cmd = 0; - uint64_t version = 0; - uint32_t i; - for (i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t cmd_offset = offset; - if (m_data.GetU32(&offset, &load_cmd, 2) == NULL) - break; - - if (load_cmd.cmd == LC_ID_DYLIB) { - if (version_cmd == 0) { - version_cmd = load_cmd.cmd; - if (m_data.GetU32(&offset, &load_cmd.dylib, 4) == NULL) - break; - version = load_cmd.dylib.current_version; - } - break; // Break for now unless there is another more complete version - // number load command in the future. - } - offset = cmd_offset + load_cmd.cmdsize; - } - - if (version_cmd == LC_ID_DYLIB) { - unsigned major = (version & 0xFFFF0000ull) >> 16; - unsigned minor = (version & 0x0000FF00ull) >> 8; - unsigned subminor = (version & 0x000000FFull); - return llvm::VersionTuple(major, minor, subminor); - } - } - return llvm::VersionTuple(); -} - -ArchSpec ObjectFileMachO::GetArchitecture() { - ModuleSP module_sp(GetModule()); - ArchSpec arch; - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - return GetArchitecture(m_header, m_data, - MachHeaderSizeFromMagic(m_header.magic)); - } - return arch; -} - -void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) { - uuid.Clear(); - base_addr = LLDB_INVALID_ADDRESS; - if (process && process->GetDynamicLoader()) { - DynamicLoader *dl = process->GetDynamicLoader(); - LazyBool using_shared_cache; - LazyBool private_shared_cache; - dl->GetSharedCacheInformation(base_addr, uuid, using_shared_cache, - private_shared_cache); - } - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf("inferior process shared cache has a UUID of %s, base address 0x%" PRIx64 , uuid.GetAsString().c_str(), base_addr); -} - -// From dyld SPI header dyld_process_info.h -typedef void *dyld_process_info; -struct lldb_copy__dyld_process_cache_info { - uuid_t cacheUUID; // UUID of cache used by process - uint64_t cacheBaseAddress; // load address of dyld shared cache - bool noCache; // process is running without a dyld cache - bool privateCache; // process is using a private copy of its dyld cache -}; - -// #including mach/mach.h pulls in machine.h & CPU_TYPE_ARM etc conflicts with llvm -// enum definitions llvm::MachO::CPU_TYPE_ARM turning them into compile errors. -// So we need to use the actual underlying types of task_t and kern_return_t -// below. -extern "C" unsigned int /*task_t*/ mach_task_self(); - -void ObjectFileMachO::GetLLDBSharedCacheUUID(addr_t &base_addr, UUID &uuid) { - uuid.Clear(); - base_addr = LLDB_INVALID_ADDRESS; - -#if defined(__APPLE__) && \ - (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) - uint8_t *(*dyld_get_all_image_infos)(void); - dyld_get_all_image_infos = - (uint8_t * (*)())dlsym(RTLD_DEFAULT, "_dyld_get_all_image_infos"); - if (dyld_get_all_image_infos) { - uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos(); - if (dyld_all_image_infos_address) { - uint32_t *version = (uint32_t *) - dyld_all_image_infos_address; // version <mach-o/dyld_images.h> - if (*version >= 13) { - uuid_t *sharedCacheUUID_address = 0; - int wordsize = sizeof(uint8_t *); - if (wordsize == 8) { - sharedCacheUUID_address = - (uuid_t *)((uint8_t *)dyld_all_image_infos_address + - 160); // sharedCacheUUID <mach-o/dyld_images.h> - if (*version >= 15) - base_addr = *(uint64_t *) ((uint8_t *) dyld_all_image_infos_address - + 176); // sharedCacheBaseAddress <mach-o/dyld_images.h> - } else { - sharedCacheUUID_address = - (uuid_t *)((uint8_t *)dyld_all_image_infos_address + - 84); // sharedCacheUUID <mach-o/dyld_images.h> - if (*version >= 15) { - base_addr = 0; - base_addr = *(uint32_t *) ((uint8_t *) dyld_all_image_infos_address - + 100); // sharedCacheBaseAddress <mach-o/dyld_images.h> - } - } - uuid = UUID::fromOptionalData(sharedCacheUUID_address, sizeof(uuid_t)); - } - } - } else { - // Exists in macOS 10.12 and later, iOS 10.0 and later - dyld SPI - dyld_process_info (*dyld_process_info_create)(unsigned int /* task_t */ task, uint64_t timestamp, unsigned int /*kern_return_t*/ *kernelError); - void (*dyld_process_info_get_cache)(void *info, void *cacheInfo); - void (*dyld_process_info_release)(dyld_process_info info); - - dyld_process_info_create = (void *(*)(unsigned int /* task_t */, uint64_t, unsigned int /*kern_return_t*/ *)) - dlsym (RTLD_DEFAULT, "_dyld_process_info_create"); - dyld_process_info_get_cache = (void (*)(void *, void *)) - dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache"); - dyld_process_info_release = (void (*)(void *)) - dlsym (RTLD_DEFAULT, "_dyld_process_info_release"); - - if (dyld_process_info_create && dyld_process_info_get_cache) { - unsigned int /*kern_return_t */ kern_ret; - dyld_process_info process_info = dyld_process_info_create(::mach_task_self(), 0, &kern_ret); - if (process_info) { - struct lldb_copy__dyld_process_cache_info sc_info; - memset (&sc_info, 0, sizeof (struct lldb_copy__dyld_process_cache_info)); - dyld_process_info_get_cache (process_info, &sc_info); - if (sc_info.cacheBaseAddress != 0) { - base_addr = sc_info.cacheBaseAddress; - uuid = UUID::fromOptionalData(sc_info.cacheUUID, sizeof(uuid_t)); - } - dyld_process_info_release (process_info); - } - } - } - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS)); - if (log && uuid.IsValid()) - log->Printf("lldb's in-memory shared cache has a UUID of %s base address of 0x%" PRIx64, uuid.GetAsString().c_str(), base_addr); -#endif -} - -llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() { - if (!m_min_os_version) { - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - - version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX || - lc.cmd == llvm::MachO::LC_VERSION_MIN_IPHONEOS || - lc.cmd == llvm::MachO::LC_VERSION_MIN_TVOS || - lc.cmd == llvm::MachO::LC_VERSION_MIN_WATCHOS) { - if (m_data.GetU32(&offset, &lc.version, - (sizeof(lc) / sizeof(uint32_t)) - 2)) { - const uint32_t xxxx = lc.version >> 16; - const uint32_t yy = (lc.version >> 8) & 0xffu; - const uint32_t zz = lc.version & 0xffu; - if (xxxx) { - m_min_os_version = llvm::VersionTuple(xxxx, yy, zz); - break; - } - } - } else if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) { - // struct build_version_command { - // uint32_t cmd; /* LC_BUILD_VERSION */ - // uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ - // /* ntools * sizeof(struct build_tool_version) */ - // uint32_t platform; /* platform */ - // uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - // uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - // uint32_t ntools; /* number of tool entries following this */ - // }; - - offset += 4; // skip platform - uint32_t minos = m_data.GetU32(&offset); - - const uint32_t xxxx = minos >> 16; - const uint32_t yy = (minos >> 8) & 0xffu; - const uint32_t zz = minos & 0xffu; - if (xxxx) { - m_min_os_version = llvm::VersionTuple(xxxx, yy, zz); - break; - } - } - - offset = load_cmd_offset + lc.cmdsize; - } - - if (!m_min_os_version) { - // Set version to an empty value so we don't keep trying to - m_min_os_version = llvm::VersionTuple(); - } - } - - return *m_min_os_version; -} - -uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions, - uint32_t num_versions) { - if (m_sdk_versions.empty()) { - lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - bool success = false; - for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - - version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == llvm::MachO::LC_VERSION_MIN_MACOSX || - lc.cmd == llvm::MachO::LC_VERSION_MIN_IPHONEOS || - lc.cmd == llvm::MachO::LC_VERSION_MIN_TVOS || - lc.cmd == llvm::MachO::LC_VERSION_MIN_WATCHOS) { - if (m_data.GetU32(&offset, &lc.version, - (sizeof(lc) / sizeof(uint32_t)) - 2)) { - const uint32_t xxxx = lc.sdk >> 16; - const uint32_t yy = (lc.sdk >> 8) & 0xffu; - const uint32_t zz = lc.sdk & 0xffu; - if (xxxx) { - m_sdk_versions.push_back(xxxx); - m_sdk_versions.push_back(yy); - m_sdk_versions.push_back(zz); - success = true; - } else { - GetModule()->ReportWarning( - "minimum OS version load command with invalid (0) version found."); - } - } - } - offset = load_cmd_offset + lc.cmdsize; - } - - if (!success) { - offset = MachHeaderSizeFromMagic(m_header.magic); - for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) { - const lldb::offset_t load_cmd_offset = offset; - - version_min_command lc; - if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL) - break; - if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) { - // struct build_version_command { - // uint32_t cmd; /* LC_BUILD_VERSION */ - // uint32_t cmdsize; /* sizeof(struct - // build_version_command) plus */ - // /* ntools * sizeof(struct - // build_tool_version) */ - // uint32_t platform; /* platform */ - // uint32_t minos; /* X.Y.Z is encoded in nibbles - // xxxx.yy.zz */ uint32_t sdk; /* X.Y.Z is encoded - // in nibbles xxxx.yy.zz */ uint32_t ntools; /* number - // of tool entries following this */ - // }; - - offset += 4; // skip platform - uint32_t minos = m_data.GetU32(&offset); - - const uint32_t xxxx = minos >> 16; - const uint32_t yy = (minos >> 8) & 0xffu; - const uint32_t zz = minos & 0xffu; - if (xxxx) { - m_sdk_versions.push_back(xxxx); - m_sdk_versions.push_back(yy); - m_sdk_versions.push_back(zz); - success = true; - } - } - offset = load_cmd_offset + lc.cmdsize; - } - } - - if (!success) { - // Push an invalid value so we don't try to find - // the version # again on the next call to this - // method. - m_sdk_versions.push_back(UINT32_MAX); - } - } - - // Legitimate version numbers will have 3 entries pushed - // on to m_sdk_versions. If we only have one value, it's - // the sentinel value indicating that this object file - // does not have a valid minimum os version #. - if (m_sdk_versions.size() > 1) { - if (versions != NULL && num_versions > 0) { - for (size_t i = 0; i < num_versions; ++i) { - if (i < m_sdk_versions.size()) - versions[i] = m_sdk_versions[i]; - else - versions[i] = 0; - } - } - return m_sdk_versions.size(); - } - // Call the superclasses version that will empty out the data - return ObjectFile::GetSDKVersion(versions, num_versions); -} - -bool ObjectFileMachO::GetIsDynamicLinkEditor() { - return m_header.filetype == llvm::MachO::MH_DYLINKER; -} - -bool ObjectFileMachO::AllowAssemblyEmulationUnwindPlans() { - return m_allow_assembly_emulation_unwind_plans; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString ObjectFileMachO::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ObjectFileMachO::GetPluginVersion() { return 1; } - -Section *ObjectFileMachO::GetMachHeaderSection() { - // Find the first address of the mach header which is the first non-zero file - // sized section whose file offset is zero. This is the base file address of - // the mach-o file which can be subtracted from the vmaddr of the other - // segments found in memory and added to the load address - ModuleSP module_sp = GetModule(); - if (!module_sp) - return nullptr; - SectionList *section_list = GetSectionList(); - if (!section_list) - return nullptr; - const size_t num_sections = section_list->GetSize(); - for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - Section *section = section_list->GetSectionAtIndex(sect_idx).get(); - if (section->GetFileOffset() == 0 && SectionIsLoadable(section)) - return section; - } - return nullptr; -} - -bool ObjectFileMachO::SectionIsLoadable(const Section *section) { - if (!section) - return false; - const bool is_dsym = (m_header.filetype == MH_DSYM); - if (section->GetFileSize() == 0 && !is_dsym) - return false; - if (section->IsThreadSpecific()) - return false; - if (GetModule().get() != section->GetModule().get()) - return false; - // Be careful with __LINKEDIT and __DWARF segments - if (section->GetName() == GetSegmentNameLINKEDIT() || - section->GetName() == GetSegmentNameDWARF()) { - // Only map __LINKEDIT and __DWARF if we have an in memory image and - // this isn't a kernel binary like a kext or mach_kernel. - const bool is_memory_image = (bool)m_process_wp.lock(); - const Strata strata = GetStrata(); - if (is_memory_image == false || strata == eStrataKernel) - return false; - } - return true; -} - -lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage( - lldb::addr_t header_load_address, const Section *header_section, - const Section *section) { - ModuleSP module_sp = GetModule(); - if (module_sp && header_section && section && - header_load_address != LLDB_INVALID_ADDRESS) { - lldb::addr_t file_addr = header_section->GetFileAddress(); - if (file_addr != LLDB_INVALID_ADDRESS && SectionIsLoadable(section)) - return section->GetFileAddress() - file_addr + header_load_address; - } - return LLDB_INVALID_ADDRESS; -} - -bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value, - bool value_is_offset) { - ModuleSP module_sp = GetModule(); - if (module_sp) { - size_t num_loaded_sections = 0; - SectionList *section_list = GetSectionList(); - if (section_list) { - const size_t num_sections = section_list->GetSize(); - - if (value_is_offset) { - // "value" is an offset to apply to each top level segment - for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - // Iterate through the object file sections to find all of the - // sections that size on disk (to avoid __PAGEZERO) and load them - SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); - if (SectionIsLoadable(section_sp.get())) - if (target.GetSectionLoadList().SetSectionLoadAddress( - section_sp, section_sp->GetFileAddress() + value)) - ++num_loaded_sections; - } - } else { - // "value" is the new base address of the mach_header, adjust each - // section accordingly - - Section *mach_header_section = GetMachHeaderSection(); - if (mach_header_section) { - for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); - - lldb::addr_t section_load_addr = - CalculateSectionLoadAddressForMemoryImage( - value, mach_header_section, section_sp.get()); - if (section_load_addr != LLDB_INVALID_ADDRESS) { - if (target.GetSectionLoadList().SetSectionLoadAddress( - section_sp, section_load_addr)) - ++num_loaded_sections; - } - } - } - } - } - return num_loaded_sections > 0; - } - return false; -} - -bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp, - const FileSpec &outfile, Status &error) { - if (process_sp) { - Target &target = process_sp->GetTarget(); - const ArchSpec target_arch = target.GetArchitecture(); - const llvm::Triple &target_triple = target_arch.GetTriple(); - if (target_triple.getVendor() == llvm::Triple::Apple && - (target_triple.getOS() == llvm::Triple::MacOSX || - target_triple.getOS() == llvm::Triple::IOS || - target_triple.getOS() == llvm::Triple::WatchOS || - target_triple.getOS() == llvm::Triple::TvOS)) { - // NEED_BRIDGEOS_TRIPLE target_triple.getOS() == llvm::Triple::BridgeOS)) { - bool make_core = false; - switch (target_arch.GetMachine()) { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::thumb: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - make_core = true; - break; - default: - error.SetErrorStringWithFormat("unsupported core architecture: %s", - target_triple.str().c_str()); - break; - } - - if (make_core) { - std::vector<segment_command_64> segment_load_commands; - // uint32_t range_info_idx = 0; - MemoryRegionInfo range_info; - Status range_error = process_sp->GetMemoryRegionInfo(0, range_info); - const uint32_t addr_byte_size = target_arch.GetAddressByteSize(); - const ByteOrder byte_order = target_arch.GetByteOrder(); - if (range_error.Success()) { - while (range_info.GetRange().GetRangeBase() != LLDB_INVALID_ADDRESS) { - const addr_t addr = range_info.GetRange().GetRangeBase(); - const addr_t size = range_info.GetRange().GetByteSize(); - - if (size == 0) - break; - - // Calculate correct protections - uint32_t prot = 0; - if (range_info.GetReadable() == MemoryRegionInfo::eYes) - prot |= VM_PROT_READ; - if (range_info.GetWritable() == MemoryRegionInfo::eYes) - prot |= VM_PROT_WRITE; - if (range_info.GetExecutable() == MemoryRegionInfo::eYes) - prot |= VM_PROT_EXECUTE; - - // printf ("[%3u] [0x%16.16" PRIx64 " - - // 0x%16.16" PRIx64 ") %c%c%c\n", - // range_info_idx, - // addr, - // size, - // (prot & VM_PROT_READ ) ? 'r' : - // '-', - // (prot & VM_PROT_WRITE ) ? 'w' : - // '-', - // (prot & VM_PROT_EXECUTE) ? 'x' : - // '-'); - - if (prot != 0) { - uint32_t cmd_type = LC_SEGMENT_64; - uint32_t segment_size = sizeof(segment_command_64); - if (addr_byte_size == 4) { - cmd_type = LC_SEGMENT; - segment_size = sizeof(segment_command); - } - segment_command_64 segment = { - cmd_type, // uint32_t cmd; - segment_size, // uint32_t cmdsize; - {0}, // char segname[16]; - addr, // uint64_t vmaddr; // uint32_t for 32-bit Mach-O - size, // uint64_t vmsize; // uint32_t for 32-bit Mach-O - 0, // uint64_t fileoff; // uint32_t for 32-bit Mach-O - size, // uint64_t filesize; // uint32_t for 32-bit Mach-O - prot, // uint32_t maxprot; - prot, // uint32_t initprot; - 0, // uint32_t nsects; - 0}; // uint32_t flags; - segment_load_commands.push_back(segment); - } else { - // No protections and a size of 1 used to be returned from old - // debugservers when we asked about a region that was past the - // last memory region and it indicates the end... - if (size == 1) - break; - } - - range_error = process_sp->GetMemoryRegionInfo( - range_info.GetRange().GetRangeEnd(), range_info); - if (range_error.Fail()) - break; - } - - StreamString buffer(Stream::eBinary, addr_byte_size, byte_order); - - mach_header_64 mach_header; - if (addr_byte_size == 8) { - mach_header.magic = MH_MAGIC_64; - } else { - mach_header.magic = MH_MAGIC; - } - mach_header.cputype = target_arch.GetMachOCPUType(); - mach_header.cpusubtype = target_arch.GetMachOCPUSubType(); - mach_header.filetype = MH_CORE; - mach_header.ncmds = segment_load_commands.size(); - mach_header.flags = 0; - mach_header.reserved = 0; - ThreadList &thread_list = process_sp->GetThreadList(); - const uint32_t num_threads = thread_list.GetSize(); - - // Make an array of LC_THREAD data items. Each one contains the - // contents of the LC_THREAD load command. The data doesn't contain - // the load command + load command size, we will add the load command - // and load command size as we emit the data. - std::vector<StreamString> LC_THREAD_datas(num_threads); - for (auto &LC_THREAD_data : LC_THREAD_datas) { - LC_THREAD_data.GetFlags().Set(Stream::eBinary); - LC_THREAD_data.SetAddressByteSize(addr_byte_size); - LC_THREAD_data.SetByteOrder(byte_order); - } - for (uint32_t thread_idx = 0; thread_idx < num_threads; - ++thread_idx) { - ThreadSP thread_sp(thread_list.GetThreadAtIndex(thread_idx)); - if (thread_sp) { - switch (mach_header.cputype) { - case llvm::MachO::CPU_TYPE_ARM64: - RegisterContextDarwin_arm64_Mach::Create_LC_THREAD( - thread_sp.get(), LC_THREAD_datas[thread_idx]); - break; - - case llvm::MachO::CPU_TYPE_ARM: - RegisterContextDarwin_arm_Mach::Create_LC_THREAD( - thread_sp.get(), LC_THREAD_datas[thread_idx]); - break; - - case llvm::MachO::CPU_TYPE_I386: - RegisterContextDarwin_i386_Mach::Create_LC_THREAD( - thread_sp.get(), LC_THREAD_datas[thread_idx]); - break; - - case llvm::MachO::CPU_TYPE_X86_64: - RegisterContextDarwin_x86_64_Mach::Create_LC_THREAD( - thread_sp.get(), LC_THREAD_datas[thread_idx]); - break; - } - } - } - - // The size of the load command is the size of the segments... - if (addr_byte_size == 8) { - mach_header.sizeofcmds = segment_load_commands.size() * - sizeof(struct segment_command_64); - } else { - mach_header.sizeofcmds = - segment_load_commands.size() * sizeof(struct segment_command); - } - - // and the size of all LC_THREAD load command - for (const auto &LC_THREAD_data : LC_THREAD_datas) { - ++mach_header.ncmds; - mach_header.sizeofcmds += 8 + LC_THREAD_data.GetSize(); - } - - printf("mach_header: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x " - "0x%8.8x 0x%8.8x\n", - mach_header.magic, mach_header.cputype, mach_header.cpusubtype, - mach_header.filetype, mach_header.ncmds, - mach_header.sizeofcmds, mach_header.flags, - mach_header.reserved); - - // Write the mach header - buffer.PutHex32(mach_header.magic); - buffer.PutHex32(mach_header.cputype); - buffer.PutHex32(mach_header.cpusubtype); - buffer.PutHex32(mach_header.filetype); - buffer.PutHex32(mach_header.ncmds); - buffer.PutHex32(mach_header.sizeofcmds); - buffer.PutHex32(mach_header.flags); - if (addr_byte_size == 8) { - buffer.PutHex32(mach_header.reserved); - } - - // Skip the mach header and all load commands and align to the next - // 0x1000 byte boundary - addr_t file_offset = buffer.GetSize() + mach_header.sizeofcmds; - if (file_offset & 0x00000fff) { - file_offset += 0x00001000ull; - file_offset &= (~0x00001000ull + 1); - } - - for (auto &segment : segment_load_commands) { - segment.fileoff = file_offset; - file_offset += segment.filesize; - } - - // Write out all of the LC_THREAD load commands - for (const auto &LC_THREAD_data : LC_THREAD_datas) { - const size_t LC_THREAD_data_size = LC_THREAD_data.GetSize(); - buffer.PutHex32(LC_THREAD); - buffer.PutHex32(8 + LC_THREAD_data_size); // cmd + cmdsize + data - buffer.Write(LC_THREAD_data.GetString().data(), - LC_THREAD_data_size); - } - - // Write out all of the segment load commands - for (const auto &segment : segment_load_commands) { - printf("0x%8.8x 0x%8.8x [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 - ") [0x%16.16" PRIx64 " 0x%16.16" PRIx64 - ") 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x]\n", - segment.cmd, segment.cmdsize, segment.vmaddr, - segment.vmaddr + segment.vmsize, segment.fileoff, - segment.filesize, segment.maxprot, segment.initprot, - segment.nsects, segment.flags); - - buffer.PutHex32(segment.cmd); - buffer.PutHex32(segment.cmdsize); - buffer.PutRawBytes(segment.segname, sizeof(segment.segname)); - if (addr_byte_size == 8) { - buffer.PutHex64(segment.vmaddr); - buffer.PutHex64(segment.vmsize); - buffer.PutHex64(segment.fileoff); - buffer.PutHex64(segment.filesize); - } else { - buffer.PutHex32(static_cast<uint32_t>(segment.vmaddr)); - buffer.PutHex32(static_cast<uint32_t>(segment.vmsize)); - buffer.PutHex32(static_cast<uint32_t>(segment.fileoff)); - buffer.PutHex32(static_cast<uint32_t>(segment.filesize)); - } - buffer.PutHex32(segment.maxprot); - buffer.PutHex32(segment.initprot); - buffer.PutHex32(segment.nsects); - buffer.PutHex32(segment.flags); - } - - File core_file; - std::string core_file_path(outfile.GetPath()); - error = FileSystem::Instance().Open(core_file, outfile, - File::eOpenOptionWrite | - File::eOpenOptionTruncate | - File::eOpenOptionCanCreate); - if (error.Success()) { - // Read 1 page at a time - uint8_t bytes[0x1000]; - // Write the mach header and load commands out to the core file - size_t bytes_written = buffer.GetString().size(); - error = core_file.Write(buffer.GetString().data(), bytes_written); - if (error.Success()) { - // Now write the file data for all memory segments in the process - for (const auto &segment : segment_load_commands) { - if (core_file.SeekFromStart(segment.fileoff) == -1) { - error.SetErrorStringWithFormat( - "unable to seek to offset 0x%" PRIx64 " in '%s'", - segment.fileoff, core_file_path.c_str()); - break; - } - - printf("Saving %" PRId64 - " bytes of data for memory region at 0x%" PRIx64 "\n", - segment.vmsize, segment.vmaddr); - addr_t bytes_left = segment.vmsize; - addr_t addr = segment.vmaddr; - Status memory_read_error; - while (bytes_left > 0 && error.Success()) { - const size_t bytes_to_read = - bytes_left > sizeof(bytes) ? sizeof(bytes) : bytes_left; - const size_t bytes_read = process_sp->ReadMemory( - addr, bytes, bytes_to_read, memory_read_error); - if (bytes_read == bytes_to_read) { - size_t bytes_written = bytes_read; - error = core_file.Write(bytes, bytes_written); - bytes_left -= bytes_read; - addr += bytes_read; - } else { - // Some pages within regions are not readable, those should - // be zero filled - memset(bytes, 0, bytes_to_read); - size_t bytes_written = bytes_to_read; - error = core_file.Write(bytes, bytes_written); - bytes_left -= bytes_to_read; - addr += bytes_to_read; - } - } - } - } - } - } else { - error.SetErrorString( - "process doesn't support getting memory region info"); - } - } - return true; // This is the right plug to handle saving core files for - // this process - } - } - return false; -} diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h deleted file mode 100644 index 196abae807e90..0000000000000 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ /dev/null @@ -1,220 +0,0 @@ -//===-- ObjectFileMachO.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ObjectFileMachO_h_ -#define liblldb_ObjectFileMachO_h_ - -#include "lldb/Core/Address.h" -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/RangeMap.h" -#include "lldb/Host/SafeMachO.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/UUID.h" - -//---------------------------------------------------------------------- -// This class needs to be hidden as eventually belongs in a plugin that -// will export the ObjectFile protocol -//---------------------------------------------------------------------- -class ObjectFileMachO : public lldb_private::ObjectFile { -public: - ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - const lldb_private::FileSpec *file, lldb::offset_t offset, - lldb::offset_t length); - - ObjectFileMachO(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); - - ~ObjectFileMachO() override = default; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::ObjectFile * - CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, const lldb_private::FileSpec *file, - lldb::offset_t file_offset, lldb::offset_t length); - - static lldb_private::ObjectFile *CreateMemoryInstance( - const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); - - static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, - lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - lldb::offset_t file_offset, - lldb::offset_t length, - lldb_private::ModuleSpecList &specs); - - static bool SaveCore(const lldb::ProcessSP &process_sp, - const lldb_private::FileSpec &outfile, - lldb_private::Status &error); - - static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset, - lldb::addr_t length); - - //------------------------------------------------------------------ - // Member Functions - //------------------------------------------------------------------ - bool ParseHeader() override; - - bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, - bool value_is_offset) override; - - lldb::ByteOrder GetByteOrder() const override; - - bool IsExecutable() const override; - - uint32_t GetAddressByteSize() const override; - - lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; - - lldb_private::Symtab *GetSymtab() override; - - bool IsStripped() override; - - void CreateSections(lldb_private::SectionList &unified_section_list) override; - - void Dump(lldb_private::Stream *s) override; - - lldb_private::ArchSpec GetArchitecture() override; - - bool GetUUID(lldb_private::UUID *uuid) override; - - uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; - - lldb_private::FileSpecList GetReExportedLibraries() override { - return m_reexported_dylibs; - } - - lldb_private::Address GetEntryPointAddress() override; - - lldb_private::Address GetBaseAddress() override; - - uint32_t GetNumThreadContexts() override; - - std::string GetIdentifierString() override; - - bool GetCorefileMainBinaryInfo (lldb::addr_t &address, lldb_private::UUID &uuid) override; - - lldb::RegisterContextSP - GetThreadContextAtIndex(uint32_t idx, lldb_private::Thread &thread) override; - - ObjectFile::Type CalculateType() override; - - ObjectFile::Strata CalculateStrata() override; - - llvm::VersionTuple GetVersion() override; - - llvm::VersionTuple GetMinimumOSVersion() override; - - uint32_t GetSDKVersion(uint32_t *versions, uint32_t num_versions) override; - - bool GetIsDynamicLinkEditor() override; - - static bool ParseHeader(lldb_private::DataExtractor &data, - lldb::offset_t *data_offset_ptr, - llvm::MachO::mach_header &header); - - bool AllowAssemblyEmulationUnwindPlans() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - static bool - GetUUID(const llvm::MachO::mach_header &header, - const lldb_private::DataExtractor &data, - lldb::offset_t lc_offset, // Offset to the first load command - lldb_private::UUID &uuid); - - static lldb_private::ArchSpec - GetArchitecture(const llvm::MachO::mach_header &header, - const lldb_private::DataExtractor &data, - lldb::offset_t lc_offset); - - // Intended for same-host arm device debugging where lldb needs to - // detect libraries in the shared cache and augment the nlist entries - // with an on-disk dyld_shared_cache file. The process will record - // the shared cache UUID so the on-disk cache can be matched or rejected - // correctly. - void GetProcessSharedCacheUUID(lldb_private::Process *, lldb::addr_t &base_addr, lldb_private::UUID &uuid); - - // Intended for same-host arm device debugging where lldb will read - // shared cache libraries out of its own memory instead of the remote - // process' memory as an optimization. If lldb's shared cache UUID - // does not match the process' shared cache UUID, this optimization - // should not be used. - void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid); - - lldb_private::Section *GetMachHeaderSection(); - - lldb::addr_t CalculateSectionLoadAddressForMemoryImage( - lldb::addr_t mach_header_load_address, - const lldb_private::Section *mach_header_section, - const lldb_private::Section *section); - - lldb_private::UUID - GetSharedCacheUUID(lldb_private::FileSpec dyld_shared_cache, - const lldb::ByteOrder byte_order, - const uint32_t addr_byte_size); - - size_t ParseSymtab(); - - typedef lldb_private::RangeArray<uint32_t, uint32_t, 8> EncryptedFileRanges; - EncryptedFileRanges GetEncryptedFileRanges(); - - struct SegmentParsingContext; - void ProcessDysymtabCommand(const llvm::MachO::load_command &load_cmd, - lldb::offset_t offset); - void ProcessSegmentCommand(const llvm::MachO::load_command &load_cmd, - lldb::offset_t offset, uint32_t cmd_idx, - SegmentParsingContext &context); - void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd, - uint32_t cmd_idx); - - bool SectionIsLoadable(const lldb_private::Section *section); - - llvm::MachO::mach_header m_header; - static const lldb_private::ConstString &GetSegmentNameTEXT(); - static const lldb_private::ConstString &GetSegmentNameDATA(); - static const lldb_private::ConstString &GetSegmentNameDATA_DIRTY(); - static const lldb_private::ConstString &GetSegmentNameDATA_CONST(); - static const lldb_private::ConstString &GetSegmentNameOBJC(); - static const lldb_private::ConstString &GetSegmentNameLINKEDIT(); - static const lldb_private::ConstString &GetSegmentNameDWARF(); - static const lldb_private::ConstString &GetSectionNameEHFrame(); - - llvm::MachO::dysymtab_command m_dysymtab; - std::vector<llvm::MachO::segment_command_64> m_mach_segments; - std::vector<llvm::MachO::section_64> m_mach_sections; - llvm::Optional<llvm::VersionTuple> m_min_os_version; - std::vector<uint32_t> m_sdk_versions; - typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray; - lldb_private::Address m_entry_point_address; - FileRangeArray m_thread_context_offsets; - bool m_thread_context_offsets_valid; - lldb_private::FileSpecList m_reexported_dylibs; - bool m_allow_assembly_emulation_unwind_plans; -}; - -#endif // liblldb_ObjectFileMachO_h_ diff --git a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt b/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt deleted file mode 100644 index 04321f2765510..0000000000000 --- a/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginObjectFilePECOFF PLUGIN - ObjectFilePECOFF.cpp - WindowsMiniDump.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - LINK_COMPONENTS - BinaryFormat - Support - ) diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp deleted file mode 100644 index d18ff617521f5..0000000000000 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ /dev/null @@ -1,1183 +0,0 @@ -//===-- ObjectFilePECOFF.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ObjectFilePECOFF.h" -#include "WindowsMiniDump.h" - -#include "lldb/Core/FileSpecList.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/SectionLoadList.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timer.h" -#include "lldb/Utility/UUID.h" -#include "llvm/BinaryFormat/COFF.h" - -#include "llvm/Object/COFFImportFile.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" - -#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ -#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 -#define OPT_HEADER_MAGIC_PE32 0x010b -#define OPT_HEADER_MAGIC_PE32_PLUS 0x020b - -using namespace lldb; -using namespace lldb_private; - -void ObjectFilePECOFF::Initialize() { - PluginManager::RegisterPlugin( - GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance, GetModuleSpecifications, SaveCore); -} - -void ObjectFilePECOFF::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString ObjectFilePECOFF::GetPluginNameStatic() { - static ConstString g_name("pe-coff"); - return g_name; -} - -const char *ObjectFilePECOFF::GetPluginDescriptionStatic() { - return "Portable Executable and Common Object File Format object file reader " - "(32 and 64 bit)"; -} - -ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp, - DataBufferSP &data_sp, - lldb::offset_t data_offset, - const lldb_private::FileSpec *file, - lldb::offset_t file_offset, - lldb::offset_t length) { - if (!data_sp) { - data_sp = MapFileData(file, length, file_offset); - if (!data_sp) - return nullptr; - data_offset = 0; - } - - if (!ObjectFilePECOFF::MagicBytesMatch(data_sp)) - return nullptr; - - // Update the data to contain the entire file if it doesn't already - if (data_sp->GetByteSize() < length) { - data_sp = MapFileData(file, length, file_offset); - if (!data_sp) - return nullptr; - } - - auto objfile_ap = llvm::make_unique<ObjectFilePECOFF>( - module_sp, data_sp, data_offset, file, file_offset, length); - if (!objfile_ap || !objfile_ap->ParseHeader()) - return nullptr; - - // Cache coff binary. - if (!objfile_ap->CreateBinary()) - return nullptr; - - return objfile_ap.release(); -} - -ObjectFile *ObjectFilePECOFF::CreateMemoryInstance( - const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { - if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)) - return nullptr; - auto objfile_ap = llvm::make_unique<ObjectFilePECOFF>( - module_sp, data_sp, process_sp, header_addr); - if (objfile_ap.get() && objfile_ap->ParseHeader()) { - return objfile_ap.release(); - } - return nullptr; -} - -size_t ObjectFilePECOFF::GetModuleSpecifications( - const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, lldb::offset_t file_offset, - lldb::offset_t length, lldb_private::ModuleSpecList &specs) { - const size_t initial_count = specs.GetSize(); - - if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) { - DataExtractor data; - data.SetData(data_sp, data_offset, length); - data.SetByteOrder(eByteOrderLittle); - - dos_header_t dos_header; - coff_header_t coff_header; - - if (ParseDOSHeader(data, dos_header)) { - lldb::offset_t offset = dos_header.e_lfanew; - uint32_t pe_signature = data.GetU32(&offset); - if (pe_signature != IMAGE_NT_SIGNATURE) - return false; - if (ParseCOFFHeader(data, &offset, coff_header)) { - ArchSpec spec; - if (coff_header.machine == MachineAmd64) { - spec.SetTriple("x86_64-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } else if (coff_header.machine == MachineX86) { - spec.SetTriple("i386-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - spec.SetTriple("i686-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } else if (coff_header.machine == MachineArmNt) { - spec.SetTriple("arm-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } - } - } - } - - return specs.GetSize() - initial_count; -} - -bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp, - const lldb_private::FileSpec &outfile, - lldb_private::Status &error) { - return SaveMiniDump(process_sp, outfile, error); -} - -bool ObjectFilePECOFF::MagicBytesMatch(DataBufferSP &data_sp) { - DataExtractor data(data_sp, eByteOrderLittle, 4); - lldb::offset_t offset = 0; - uint16_t magic = data.GetU16(&offset); - return magic == IMAGE_DOS_SIGNATURE; -} - -lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) { - // TODO: We need to complete this mapping of COFF symbol types to LLDB ones. - // For now, here's a hack to make sure our function have types. - const auto complex_type = - coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT; - if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) { - return lldb::eSymbolTypeCode; - } - return lldb::eSymbolTypeInvalid; -} - -bool ObjectFilePECOFF::CreateBinary() { - if (m_owningbin) - return true; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - - auto binary = llvm::object::createBinary(m_file.GetPath()); - if (!binary) { - if (log) - log->Printf("ObjectFilePECOFF::CreateBinary() - failed to create binary " - "for file (%s): %s", - m_file ? m_file.GetPath().c_str() : "<NULL>", - errorToErrorCode(binary.takeError()).message().c_str()); - return false; - } - - // Make sure we only handle COFF format. - if (!binary->getBinary()->isCOFF() && - !binary->getBinary()->isCOFFImportFile()) - return false; - - m_owningbin = OWNBINType(std::move(*binary)); - if (log) - log->Printf("%p ObjectFilePECOFF::CreateBinary() module = %p (%s), file = " - "%s, binary = %p (Bin = %p)", - static_cast<void *>(this), - static_cast<void *>(GetModule().get()), - GetModule()->GetSpecificationDescription().c_str(), - m_file ? m_file.GetPath().c_str() : "<NULL>", - static_cast<void *>(m_owningbin.getPointer()), - static_cast<void *>(m_owningbin->getBinary())); - return true; -} - -ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, - DataBufferSP &data_sp, - lldb::offset_t data_offset, - const FileSpec *file, - lldb::offset_t file_offset, - lldb::offset_t length) - : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), - m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(), - m_entry_point_address(), m_deps_filespec(), m_owningbin() { - ::memset(&m_dos_header, 0, sizeof(m_dos_header)); - ::memset(&m_coff_header, 0, sizeof(m_coff_header)); - ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); -} - -ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, - DataBufferSP &header_data_sp, - const lldb::ProcessSP &process_sp, - addr_t header_addr) - : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), - m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(), - m_entry_point_address(), m_deps_filespec(), m_owningbin() { - ::memset(&m_dos_header, 0, sizeof(m_dos_header)); - ::memset(&m_coff_header, 0, sizeof(m_coff_header)); - ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); -} - -ObjectFilePECOFF::~ObjectFilePECOFF() {} - -bool ObjectFilePECOFF::ParseHeader() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - m_sect_headers.clear(); - m_data.SetByteOrder(eByteOrderLittle); - lldb::offset_t offset = 0; - - if (ParseDOSHeader(m_data, m_dos_header)) { - offset = m_dos_header.e_lfanew; - uint32_t pe_signature = m_data.GetU32(&offset); - if (pe_signature != IMAGE_NT_SIGNATURE) - return false; - if (ParseCOFFHeader(m_data, &offset, m_coff_header)) { - if (m_coff_header.hdrsize > 0) - ParseCOFFOptionalHeader(&offset); - ParseSectionHeaders(offset); - } - return true; - } - } - return false; -} - -bool ObjectFilePECOFF::SetLoadAddress(Target &target, addr_t value, - bool value_is_offset) { - bool changed = false; - ModuleSP module_sp = GetModule(); - if (module_sp) { - size_t num_loaded_sections = 0; - SectionList *section_list = GetSectionList(); - if (section_list) { - if (!value_is_offset) { - value -= m_image_base; - } - - const size_t num_sections = section_list->GetSize(); - size_t sect_idx = 0; - - for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - // Iterate through the object file sections to find all of the sections - // that have SHF_ALLOC in their flag bits. - SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); - if (section_sp && !section_sp->IsThreadSpecific()) { - if (target.GetSectionLoadList().SetSectionLoadAddress( - section_sp, section_sp->GetFileAddress() + value)) - ++num_loaded_sections; - } - } - changed = num_loaded_sections > 0; - } - } - return changed; -} - -ByteOrder ObjectFilePECOFF::GetByteOrder() const { return eByteOrderLittle; } - -bool ObjectFilePECOFF::IsExecutable() const { - return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0; -} - -uint32_t ObjectFilePECOFF::GetAddressByteSize() const { - if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS) - return 8; - else if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32) - return 4; - return 4; -} - -//---------------------------------------------------------------------- -// NeedsEndianSwap -// -// Return true if an endian swap needs to occur when extracting data from this -// file. -//---------------------------------------------------------------------- -bool ObjectFilePECOFF::NeedsEndianSwap() const { -#if defined(__LITTLE_ENDIAN__) - return false; -#else - return true; -#endif -} -//---------------------------------------------------------------------- -// ParseDOSHeader -//---------------------------------------------------------------------- -bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data, - dos_header_t &dos_header) { - bool success = false; - lldb::offset_t offset = 0; - success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header)); - - if (success) { - dos_header.e_magic = data.GetU16(&offset); // Magic number - success = dos_header.e_magic == IMAGE_DOS_SIGNATURE; - - if (success) { - dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file - dos_header.e_cp = data.GetU16(&offset); // Pages in file - dos_header.e_crlc = data.GetU16(&offset); // Relocations - dos_header.e_cparhdr = - data.GetU16(&offset); // Size of header in paragraphs - dos_header.e_minalloc = - data.GetU16(&offset); // Minimum extra paragraphs needed - dos_header.e_maxalloc = - data.GetU16(&offset); // Maximum extra paragraphs needed - dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value - dos_header.e_sp = data.GetU16(&offset); // Initial SP value - dos_header.e_csum = data.GetU16(&offset); // Checksum - dos_header.e_ip = data.GetU16(&offset); // Initial IP value - dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value - dos_header.e_lfarlc = - data.GetU16(&offset); // File address of relocation table - dos_header.e_ovno = data.GetU16(&offset); // Overlay number - - dos_header.e_res[0] = data.GetU16(&offset); // Reserved words - dos_header.e_res[1] = data.GetU16(&offset); // Reserved words - dos_header.e_res[2] = data.GetU16(&offset); // Reserved words - dos_header.e_res[3] = data.GetU16(&offset); // Reserved words - - dos_header.e_oemid = - data.GetU16(&offset); // OEM identifier (for e_oeminfo) - dos_header.e_oeminfo = - data.GetU16(&offset); // OEM information; e_oemid specific - dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words - dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words - - dos_header.e_lfanew = - data.GetU32(&offset); // File address of new exe header - } - } - if (!success) - memset(&dos_header, 0, sizeof(dos_header)); - return success; -} - -//---------------------------------------------------------------------- -// ParserCOFFHeader -//---------------------------------------------------------------------- -bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data, - lldb::offset_t *offset_ptr, - coff_header_t &coff_header) { - bool success = - data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header)); - if (success) { - coff_header.machine = data.GetU16(offset_ptr); - coff_header.nsects = data.GetU16(offset_ptr); - coff_header.modtime = data.GetU32(offset_ptr); - coff_header.symoff = data.GetU32(offset_ptr); - coff_header.nsyms = data.GetU32(offset_ptr); - coff_header.hdrsize = data.GetU16(offset_ptr); - coff_header.flags = data.GetU16(offset_ptr); - } - if (!success) - memset(&coff_header, 0, sizeof(coff_header)); - return success; -} - -bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) { - bool success = false; - const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize; - if (*offset_ptr < end_offset) { - success = true; - m_coff_header_opt.magic = m_data.GetU16(offset_ptr); - m_coff_header_opt.major_linker_version = m_data.GetU8(offset_ptr); - m_coff_header_opt.minor_linker_version = m_data.GetU8(offset_ptr); - m_coff_header_opt.code_size = m_data.GetU32(offset_ptr); - m_coff_header_opt.data_size = m_data.GetU32(offset_ptr); - m_coff_header_opt.bss_size = m_data.GetU32(offset_ptr); - m_coff_header_opt.entry = m_data.GetU32(offset_ptr); - m_coff_header_opt.code_offset = m_data.GetU32(offset_ptr); - - const uint32_t addr_byte_size = GetAddressByteSize(); - - if (*offset_ptr < end_offset) { - if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32) { - // PE32 only - m_coff_header_opt.data_offset = m_data.GetU32(offset_ptr); - } else - m_coff_header_opt.data_offset = 0; - - if (*offset_ptr < end_offset) { - m_coff_header_opt.image_base = - m_data.GetMaxU64(offset_ptr, addr_byte_size); - m_coff_header_opt.sect_alignment = m_data.GetU32(offset_ptr); - m_coff_header_opt.file_alignment = m_data.GetU32(offset_ptr); - m_coff_header_opt.major_os_system_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.minor_os_system_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.major_image_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.minor_image_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.major_subsystem_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.minor_subsystem_version = m_data.GetU16(offset_ptr); - m_coff_header_opt.reserved1 = m_data.GetU32(offset_ptr); - m_coff_header_opt.image_size = m_data.GetU32(offset_ptr); - m_coff_header_opt.header_size = m_data.GetU32(offset_ptr); - m_coff_header_opt.checksum = m_data.GetU32(offset_ptr); - m_coff_header_opt.subsystem = m_data.GetU16(offset_ptr); - m_coff_header_opt.dll_flags = m_data.GetU16(offset_ptr); - m_coff_header_opt.stack_reserve_size = - m_data.GetMaxU64(offset_ptr, addr_byte_size); - m_coff_header_opt.stack_commit_size = - m_data.GetMaxU64(offset_ptr, addr_byte_size); - m_coff_header_opt.heap_reserve_size = - m_data.GetMaxU64(offset_ptr, addr_byte_size); - m_coff_header_opt.heap_commit_size = - m_data.GetMaxU64(offset_ptr, addr_byte_size); - m_coff_header_opt.loader_flags = m_data.GetU32(offset_ptr); - uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr); - m_coff_header_opt.data_dirs.clear(); - m_coff_header_opt.data_dirs.resize(num_data_dir_entries); - uint32_t i; - for (i = 0; i < num_data_dir_entries; i++) { - m_coff_header_opt.data_dirs[i].vmaddr = m_data.GetU32(offset_ptr); - m_coff_header_opt.data_dirs[i].vmsize = m_data.GetU32(offset_ptr); - } - - m_file_offset = m_coff_header_opt.image_base; - m_image_base = m_coff_header_opt.image_base; - } - } - } - // Make sure we are on track for section data which follows - *offset_ptr = end_offset; - return success; -} - -DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) { - if (m_file) { - // A bit of a hack, but we intend to write to this buffer, so we can't - // mmap it. - auto buffer_sp = MapFileData(m_file, size, offset); - return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); - } - ProcessSP process_sp(m_process_wp.lock()); - DataExtractor data; - if (process_sp) { - auto data_ap = llvm::make_unique<DataBufferHeap>(size, 0); - Status readmem_error; - size_t bytes_read = - process_sp->ReadMemory(m_image_base + offset, data_ap->GetBytes(), - data_ap->GetByteSize(), readmem_error); - if (bytes_read == size) { - DataBufferSP buffer_sp(data_ap.release()); - data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); - } - } - return data; -} - -//---------------------------------------------------------------------- -// ParseSectionHeaders -//---------------------------------------------------------------------- -bool ObjectFilePECOFF::ParseSectionHeaders( - uint32_t section_header_data_offset) { - const uint32_t nsects = m_coff_header.nsects; - m_sect_headers.clear(); - - if (nsects > 0) { - const size_t section_header_byte_size = nsects * sizeof(section_header_t); - DataExtractor section_header_data = - ReadImageData(section_header_data_offset, section_header_byte_size); - - lldb::offset_t offset = 0; - if (section_header_data.ValidOffsetForDataOfSize( - offset, section_header_byte_size)) { - m_sect_headers.resize(nsects); - - for (uint32_t idx = 0; idx < nsects; ++idx) { - const void *name_data = section_header_data.GetData(&offset, 8); - if (name_data) { - memcpy(m_sect_headers[idx].name, name_data, 8); - m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset); - m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset); - m_sect_headers[idx].size = section_header_data.GetU32(&offset); - m_sect_headers[idx].offset = section_header_data.GetU32(&offset); - m_sect_headers[idx].reloff = section_header_data.GetU32(&offset); - m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset); - m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset); - m_sect_headers[idx].nline = section_header_data.GetU16(&offset); - m_sect_headers[idx].flags = section_header_data.GetU32(&offset); - } - } - } - } - - return !m_sect_headers.empty(); -} - -llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t §) { - llvm::StringRef hdr_name(sect.name, llvm::array_lengthof(sect.name)); - hdr_name = hdr_name.split('\0').first; - if (hdr_name.consume_front("/")) { - lldb::offset_t stroff; - if (!to_integer(hdr_name, stroff, 10)) - return ""; - lldb::offset_t string_file_offset = - m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff; - if (const char *name = m_data.GetCStr(&string_file_offset)) - return name; - return ""; - } - return hdr_name; -} - -//---------------------------------------------------------------------- -// GetNListSymtab -//---------------------------------------------------------------------- -Symtab *ObjectFilePECOFF::GetSymtab() { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_symtab_ap.get() == NULL) { - SectionList *sect_list = GetSectionList(); - m_symtab_ap.reset(new Symtab(this)); - std::lock_guard<std::recursive_mutex> guard(m_symtab_ap->GetMutex()); - - const uint32_t num_syms = m_coff_header.nsyms; - - if (m_file && num_syms > 0 && m_coff_header.symoff > 0) { - const uint32_t symbol_size = 18; - const size_t symbol_data_size = num_syms * symbol_size; - // Include the 4-byte string table size at the end of the symbols - DataExtractor symtab_data = - ReadImageData(m_coff_header.symoff, symbol_data_size + 4); - lldb::offset_t offset = symbol_data_size; - const uint32_t strtab_size = symtab_data.GetU32(&offset); - if (strtab_size > 0) { - DataExtractor strtab_data = ReadImageData( - m_coff_header.symoff + symbol_data_size, strtab_size); - - // First 4 bytes should be zeroed after strtab_size has been read, - // because it is used as offset 0 to encode a NULL string. - uint32_t *strtab_data_start = const_cast<uint32_t *>( - reinterpret_cast<const uint32_t *>(strtab_data.GetDataStart())); - strtab_data_start[0] = 0; - - offset = 0; - std::string symbol_name; - Symbol *symbols = m_symtab_ap->Resize(num_syms); - for (uint32_t i = 0; i < num_syms; ++i) { - coff_symbol_t symbol; - const uint32_t symbol_offset = offset; - const char *symbol_name_cstr = NULL; - // If the first 4 bytes of the symbol string are zero, then they - // are followed by a 4-byte string table offset. Else these - // 8 bytes contain the symbol name - if (symtab_data.GetU32(&offset) == 0) { - // Long string that doesn't fit into the symbol table name, so - // now we must read the 4 byte string table offset - uint32_t strtab_offset = symtab_data.GetU32(&offset); - symbol_name_cstr = strtab_data.PeekCStr(strtab_offset); - symbol_name.assign(symbol_name_cstr); - } else { - // Short string that fits into the symbol table name which is 8 - // bytes - offset += sizeof(symbol.name) - 4; // Skip remaining - symbol_name_cstr = symtab_data.PeekCStr(symbol_offset); - if (symbol_name_cstr == NULL) - break; - symbol_name.assign(symbol_name_cstr, sizeof(symbol.name)); - } - symbol.value = symtab_data.GetU32(&offset); - symbol.sect = symtab_data.GetU16(&offset); - symbol.type = symtab_data.GetU16(&offset); - symbol.storage = symtab_data.GetU8(&offset); - symbol.naux = symtab_data.GetU8(&offset); - symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str())); - if ((int16_t)symbol.sect >= 1) { - Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect - 1), - symbol.value); - symbols[i].GetAddressRef() = symbol_addr; - symbols[i].SetType(MapSymbolType(symbol.type)); - } - - if (symbol.naux > 0) { - i += symbol.naux; - offset += symbol_size; - } - } - } - } - - // Read export header - if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() && - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 && - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) { - export_directory_entry export_table; - uint32_t data_start = - m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr; - - uint32_t address_rva = data_start; - if (m_file) { - Address address(m_coff_header_opt.image_base + data_start, sect_list); - address_rva = - address.GetSection()->GetFileOffset() + address.GetOffset(); - } - DataExtractor symtab_data = - ReadImageData(address_rva, m_coff_header_opt.data_dirs[0].vmsize); - lldb::offset_t offset = 0; - - // Read export_table header - export_table.characteristics = symtab_data.GetU32(&offset); - export_table.time_date_stamp = symtab_data.GetU32(&offset); - export_table.major_version = symtab_data.GetU16(&offset); - export_table.minor_version = symtab_data.GetU16(&offset); - export_table.name = symtab_data.GetU32(&offset); - export_table.base = symtab_data.GetU32(&offset); - export_table.number_of_functions = symtab_data.GetU32(&offset); - export_table.number_of_names = symtab_data.GetU32(&offset); - export_table.address_of_functions = symtab_data.GetU32(&offset); - export_table.address_of_names = symtab_data.GetU32(&offset); - export_table.address_of_name_ordinals = symtab_data.GetU32(&offset); - - bool has_ordinal = export_table.address_of_name_ordinals != 0; - - lldb::offset_t name_offset = export_table.address_of_names - data_start; - lldb::offset_t name_ordinal_offset = - export_table.address_of_name_ordinals - data_start; - - Symbol *symbols = m_symtab_ap->Resize(export_table.number_of_names); - - std::string symbol_name; - - // Read each export table entry - for (size_t i = 0; i < export_table.number_of_names; ++i) { - uint32_t name_ordinal = - has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i; - uint32_t name_address = symtab_data.GetU32(&name_offset); - - const char *symbol_name_cstr = - symtab_data.PeekCStr(name_address - data_start); - symbol_name.assign(symbol_name_cstr); - - lldb::offset_t function_offset = export_table.address_of_functions - - data_start + - sizeof(uint32_t) * name_ordinal; - uint32_t function_rva = symtab_data.GetU32(&function_offset); - - Address symbol_addr(m_coff_header_opt.image_base + function_rva, - sect_list); - symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str())); - symbols[i].GetAddressRef() = symbol_addr; - symbols[i].SetType(lldb::eSymbolTypeCode); - symbols[i].SetDebug(true); - } - } - m_symtab_ap->CalculateSymbolSizes(); - } - } - return m_symtab_ap.get(); -} - -bool ObjectFilePECOFF::IsStripped() { - // TODO: determine this for COFF - return false; -} - -void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) { - if (m_sections_ap) - return; - m_sections_ap.reset(new SectionList()); - - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - const uint32_t nsects = m_sect_headers.size(); - ModuleSP module_sp(GetModule()); - for (uint32_t idx = 0; idx < nsects; ++idx) { - ConstString const_sect_name(GetSectionName(m_sect_headers[idx])); - static ConstString g_code_sect_name(".code"); - static ConstString g_CODE_sect_name("CODE"); - static ConstString g_data_sect_name(".data"); - static ConstString g_DATA_sect_name("DATA"); - static ConstString g_bss_sect_name(".bss"); - static ConstString g_BSS_sect_name("BSS"); - static ConstString g_debug_sect_name(".debug"); - static ConstString g_reloc_sect_name(".reloc"); - static ConstString g_stab_sect_name(".stab"); - static ConstString g_stabstr_sect_name(".stabstr"); - static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev"); - static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges"); - static ConstString g_sect_name_dwarf_debug_frame(".debug_frame"); - static ConstString g_sect_name_dwarf_debug_info(".debug_info"); - static ConstString g_sect_name_dwarf_debug_line(".debug_line"); - static ConstString g_sect_name_dwarf_debug_loc(".debug_loc"); - static ConstString g_sect_name_dwarf_debug_loclists(".debug_loclists"); - static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo"); - static ConstString g_sect_name_dwarf_debug_names(".debug_names"); - static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames"); - static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes"); - static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges"); - static ConstString g_sect_name_dwarf_debug_str(".debug_str"); - static ConstString g_sect_name_dwarf_debug_types(".debug_types"); - static ConstString g_sect_name_eh_frame(".eh_frame"); - static ConstString g_sect_name_go_symtab(".gosymtab"); - SectionType section_type = eSectionTypeOther; - if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE && - ((const_sect_name == g_code_sect_name) || - (const_sect_name == g_CODE_sect_name))) { - section_type = eSectionTypeCode; - } else if (m_sect_headers[idx].flags & - llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA && - ((const_sect_name == g_data_sect_name) || - (const_sect_name == g_DATA_sect_name))) { - if (m_sect_headers[idx].size == 0 && m_sect_headers[idx].offset == 0) - section_type = eSectionTypeZeroFill; - else - section_type = eSectionTypeData; - } else if (m_sect_headers[idx].flags & - llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA && - ((const_sect_name == g_bss_sect_name) || - (const_sect_name == g_BSS_sect_name))) { - if (m_sect_headers[idx].size == 0) - section_type = eSectionTypeZeroFill; - else - section_type = eSectionTypeData; - } else if (const_sect_name == g_debug_sect_name) { - section_type = eSectionTypeDebug; - } else if (const_sect_name == g_stabstr_sect_name) { - section_type = eSectionTypeDataCString; - } else if (const_sect_name == g_reloc_sect_name) { - section_type = eSectionTypeOther; - } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev) - section_type = eSectionTypeDWARFDebugAbbrev; - else if (const_sect_name == g_sect_name_dwarf_debug_aranges) - section_type = eSectionTypeDWARFDebugAranges; - else if (const_sect_name == g_sect_name_dwarf_debug_frame) - section_type = eSectionTypeDWARFDebugFrame; - else if (const_sect_name == g_sect_name_dwarf_debug_info) - section_type = eSectionTypeDWARFDebugInfo; - else if (const_sect_name == g_sect_name_dwarf_debug_line) - section_type = eSectionTypeDWARFDebugLine; - else if (const_sect_name == g_sect_name_dwarf_debug_loc) - section_type = eSectionTypeDWARFDebugLoc; - else if (const_sect_name == g_sect_name_dwarf_debug_loclists) - section_type = eSectionTypeDWARFDebugLocLists; - else if (const_sect_name == g_sect_name_dwarf_debug_macinfo) - section_type = eSectionTypeDWARFDebugMacInfo; - else if (const_sect_name == g_sect_name_dwarf_debug_names) - section_type = eSectionTypeDWARFDebugNames; - else if (const_sect_name == g_sect_name_dwarf_debug_pubnames) - section_type = eSectionTypeDWARFDebugPubNames; - else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes) - section_type = eSectionTypeDWARFDebugPubTypes; - else if (const_sect_name == g_sect_name_dwarf_debug_ranges) - section_type = eSectionTypeDWARFDebugRanges; - else if (const_sect_name == g_sect_name_dwarf_debug_str) - section_type = eSectionTypeDWARFDebugStr; - else if (const_sect_name == g_sect_name_dwarf_debug_types) - section_type = eSectionTypeDWARFDebugTypes; - else if (const_sect_name == g_sect_name_eh_frame) - section_type = eSectionTypeEHFrame; - else if (const_sect_name == g_sect_name_go_symtab) - section_type = eSectionTypeGoSymtab; - else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) { - section_type = eSectionTypeCode; - } else if (m_sect_headers[idx].flags & - llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) { - section_type = eSectionTypeData; - } else if (m_sect_headers[idx].flags & - llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) { - if (m_sect_headers[idx].size == 0) - section_type = eSectionTypeZeroFill; - else - section_type = eSectionTypeData; - } - - // Use a segment ID of the segment index shifted left by 8 so they - // never conflict with any of the sections. - SectionSP section_sp(new Section( - module_sp, // Module to which this section belongs - this, // Object file to which this section belongs - idx + 1, // Section ID is the 1 based segment index shifted right by - // 8 bits as not to collide with any of the 256 section IDs - // that are possible - const_sect_name, // Name of this section - section_type, // This section is a container of other sections. - m_coff_header_opt.image_base + - m_sect_headers[idx].vmaddr, // File VM address == addresses as - // they are found in the object file - m_sect_headers[idx].vmsize, // VM size in bytes of this section - m_sect_headers[idx] - .offset, // Offset to the data for this section in the file - m_sect_headers[idx] - .size, // Size in bytes of this section as found in the file - m_coff_header_opt.sect_alignment, // Section alignment - m_sect_headers[idx].flags)); // Flags for this section - - // section_sp->SetIsEncrypted (segment_is_encrypted); - - unified_section_list.AddSection(section_sp); - m_sections_ap->AddSection(section_sp); - } - } -} - -bool ObjectFilePECOFF::GetUUID(UUID *uuid) { return false; } - -uint32_t ObjectFilePECOFF::ParseDependentModules() { - ModuleSP module_sp(GetModule()); - if (!module_sp) - return 0; - - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_deps_filespec) - return m_deps_filespec->GetSize(); - - // Cache coff binary if it is not done yet. - if (!CreateBinary()) - return 0; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf("%p ObjectFilePECOFF::ParseDependentModules() module = %p " - "(%s), binary = %p (Bin = %p)", - static_cast<void *>(this), static_cast<void *>(module_sp.get()), - module_sp->GetSpecificationDescription().c_str(), - static_cast<void *>(m_owningbin.getPointer()), - m_owningbin ? static_cast<void *>(m_owningbin->getBinary()) - : nullptr); - - auto COFFObj = - llvm::dyn_cast<llvm::object::COFFObjectFile>(m_owningbin->getBinary()); - if (!COFFObj) - return 0; - - m_deps_filespec = FileSpecList(); - - for (const auto &entry : COFFObj->import_directories()) { - llvm::StringRef dll_name; - auto ec = entry.getName(dll_name); - // Report a bogus entry. - if (ec != std::error_code()) { - if (log) - log->Printf("ObjectFilePECOFF::ParseDependentModules() - failed to get " - "import directory entry name: %s", - ec.message().c_str()); - continue; - } - - // At this moment we only have the base name of the DLL. The full path can - // only be seen after the dynamic loading. Our best guess is Try to get it - // with the help of the object file's directory. - llvm::SmallString<128> dll_fullpath; - FileSpec dll_specs(dll_name); - dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString()); - - if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath)) - m_deps_filespec->Append(FileSpec(dll_fullpath)); - else { - // Known DLLs or DLL not found in the object file directory. - m_deps_filespec->Append(FileSpec(dll_name)); - } - } - return m_deps_filespec->GetSize(); -} - -uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) { - auto num_modules = ParseDependentModules(); - auto original_size = files.GetSize(); - - for (unsigned i = 0; i < num_modules; ++i) - files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i)); - - return files.GetSize() - original_size; -} - -lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() { - if (m_entry_point_address.IsValid()) - return m_entry_point_address; - - if (!ParseHeader() || !IsExecutable()) - return m_entry_point_address; - - SectionList *section_list = GetSectionList(); - addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base; - - if (!section_list) - m_entry_point_address.SetOffset(file_addr); - else - m_entry_point_address.ResolveAddressUsingFileSections(file_addr, section_list); - return m_entry_point_address; -} - -//---------------------------------------------------------------------- -// Dump -// -// Dump the specifics of the runtime file container (such as any headers -// segments, sections, etc). -//---------------------------------------------------------------------- -void ObjectFilePECOFF::Dump(Stream *s) { - ModuleSP module_sp(GetModule()); - if (module_sp) { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - s->Printf("%p: ", static_cast<void *>(this)); - s->Indent(); - s->PutCString("ObjectFilePECOFF"); - - ArchSpec header_arch = GetArchitecture(); - - *s << ", file = '" << m_file - << "', arch = " << header_arch.GetArchitectureName() << "\n"; - - SectionList *sections = GetSectionList(); - if (sections) - sections->Dump(s, NULL, true, UINT32_MAX); - - if (m_symtab_ap.get()) - m_symtab_ap->Dump(s, NULL, eSortOrderNone); - - if (m_dos_header.e_magic) - DumpDOSHeader(s, m_dos_header); - if (m_coff_header.machine) { - DumpCOFFHeader(s, m_coff_header); - if (m_coff_header.hdrsize) - DumpOptCOFFHeader(s, m_coff_header_opt); - } - s->EOL(); - DumpSectionHeaders(s); - s->EOL(); - - DumpDependentModules(s); - s->EOL(); - } -} - -//---------------------------------------------------------------------- -// DumpDOSHeader -// -// Dump the MS-DOS header to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpDOSHeader(Stream *s, const dos_header_t &header) { - s->PutCString("MSDOS Header\n"); - s->Printf(" e_magic = 0x%4.4x\n", header.e_magic); - s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp); - s->Printf(" e_cp = 0x%4.4x\n", header.e_cp); - s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc); - s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr); - s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc); - s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc); - s->Printf(" e_ss = 0x%4.4x\n", header.e_ss); - s->Printf(" e_sp = 0x%4.4x\n", header.e_sp); - s->Printf(" e_csum = 0x%4.4x\n", header.e_csum); - s->Printf(" e_ip = 0x%4.4x\n", header.e_ip); - s->Printf(" e_cs = 0x%4.4x\n", header.e_cs); - s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc); - s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno); - s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n", - header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]); - s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid); - s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo); - s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, " - "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n", - header.e_res2[0], header.e_res2[1], header.e_res2[2], - header.e_res2[3], header.e_res2[4], header.e_res2[5], - header.e_res2[6], header.e_res2[7], header.e_res2[8], - header.e_res2[9]); - s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew); -} - -//---------------------------------------------------------------------- -// DumpCOFFHeader -// -// Dump the COFF header to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpCOFFHeader(Stream *s, const coff_header_t &header) { - s->PutCString("COFF Header\n"); - s->Printf(" machine = 0x%4.4x\n", header.machine); - s->Printf(" nsects = 0x%4.4x\n", header.nsects); - s->Printf(" modtime = 0x%8.8x\n", header.modtime); - s->Printf(" symoff = 0x%8.8x\n", header.symoff); - s->Printf(" nsyms = 0x%8.8x\n", header.nsyms); - s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize); -} - -//---------------------------------------------------------------------- -// DumpOptCOFFHeader -// -// Dump the optional COFF header to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s, - const coff_opt_header_t &header) { - s->PutCString("Optional COFF Header\n"); - s->Printf(" magic = 0x%4.4x\n", header.magic); - s->Printf(" major_linker_version = 0x%2.2x\n", - header.major_linker_version); - s->Printf(" minor_linker_version = 0x%2.2x\n", - header.minor_linker_version); - s->Printf(" code_size = 0x%8.8x\n", header.code_size); - s->Printf(" data_size = 0x%8.8x\n", header.data_size); - s->Printf(" bss_size = 0x%8.8x\n", header.bss_size); - s->Printf(" entry = 0x%8.8x\n", header.entry); - s->Printf(" code_offset = 0x%8.8x\n", header.code_offset); - s->Printf(" data_offset = 0x%8.8x\n", header.data_offset); - s->Printf(" image_base = 0x%16.16" PRIx64 "\n", - header.image_base); - s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment); - s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment); - s->Printf(" major_os_system_version = 0x%4.4x\n", - header.major_os_system_version); - s->Printf(" minor_os_system_version = 0x%4.4x\n", - header.minor_os_system_version); - s->Printf(" major_image_version = 0x%4.4x\n", - header.major_image_version); - s->Printf(" minor_image_version = 0x%4.4x\n", - header.minor_image_version); - s->Printf(" major_subsystem_version = 0x%4.4x\n", - header.major_subsystem_version); - s->Printf(" minor_subsystem_version = 0x%4.4x\n", - header.minor_subsystem_version); - s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1); - s->Printf(" image_size = 0x%8.8x\n", header.image_size); - s->Printf(" header_size = 0x%8.8x\n", header.header_size); - s->Printf(" checksum = 0x%8.8x\n", header.checksum); - s->Printf(" subsystem = 0x%4.4x\n", header.subsystem); - s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags); - s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n", - header.stack_reserve_size); - s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n", - header.stack_commit_size); - s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n", - header.heap_reserve_size); - s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n", - header.heap_commit_size); - s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags); - s->Printf(" num_data_dir_entries = 0x%8.8x\n", - (uint32_t)header.data_dirs.size()); - uint32_t i; - for (i = 0; i < header.data_dirs.size(); i++) { - s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i, - header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize); - } -} -//---------------------------------------------------------------------- -// DumpSectionHeader -// -// Dump a single ELF section header to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpSectionHeader(Stream *s, - const section_header_t &sh) { - std::string name = GetSectionName(sh); - s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x " - "0x%4.4x 0x%8.8x\n", - name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff, - sh.lineoff, sh.nreloc, sh.nline, sh.flags); -} - -//---------------------------------------------------------------------- -// DumpSectionHeaders -// -// Dump all of the ELF section header to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) { - - s->PutCString("Section Headers\n"); - s->PutCString("IDX name vm addr vm size file off file " - "size reloc off line off nreloc nline flags\n"); - s->PutCString("==== ---------------- ---------- ---------- ---------- " - "---------- ---------- ---------- ------ ------ ----------\n"); - - uint32_t idx = 0; - SectionHeaderCollIter pos, end = m_sect_headers.end(); - - for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) { - s->Printf("[%2u] ", idx); - ObjectFilePECOFF::DumpSectionHeader(s, *pos); - } -} - -//---------------------------------------------------------------------- -// DumpDependentModules -// -// Dump all of the dependent modules to the specified output stream -//---------------------------------------------------------------------- -void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) { - auto num_modules = ParseDependentModules(); - if (num_modules > 0) { - s->PutCString("Dependent Modules\n"); - for (unsigned i = 0; i < num_modules; ++i) { - auto spec = m_deps_filespec->GetFileSpecAtIndex(i); - s->Printf(" %s\n", spec.GetFilename().GetCString()); - } - } -} - -bool ObjectFilePECOFF::IsWindowsSubsystem() { - switch (m_coff_header_opt.subsystem) { - case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE: - case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI: - case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI: - case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS: - case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI: - case llvm::COFF::IMAGE_SUBSYSTEM_XBOX: - case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION: - return true; - default: - return false; - } -} - -ArchSpec ObjectFilePECOFF::GetArchitecture() { - uint16_t machine = m_coff_header.machine; - switch (machine) { - default: - break; - case llvm::COFF::IMAGE_FILE_MACHINE_AMD64: - case llvm::COFF::IMAGE_FILE_MACHINE_I386: - case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC: - case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP: - case llvm::COFF::IMAGE_FILE_MACHINE_ARM: - case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT: - case llvm::COFF::IMAGE_FILE_MACHINE_THUMB: - ArchSpec arch; - arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE, - IsWindowsSubsystem() ? llvm::Triple::Win32 - : llvm::Triple::UnknownOS); - return arch; - } - return ArchSpec(); -} - -ObjectFile::Type ObjectFilePECOFF::CalculateType() { - if (m_coff_header.machine != 0) { - if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0) - return eTypeExecutable; - else - return eTypeSharedLibrary; - } - return eTypeExecutable; -} - -ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; } - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -ConstString ObjectFilePECOFF::GetPluginName() { return GetPluginNameStatic(); } - -uint32_t ObjectFilePECOFF::GetPluginVersion() { return 1; } diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h deleted file mode 100644 index 9fd313f26a0a2..0000000000000 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ /dev/null @@ -1,294 +0,0 @@ -//===-- ObjectFilePECOFF.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ObjectFilePECOFF_h_ -#define liblldb_ObjectFilePECOFF_h_ - -#include <vector> - -#include "lldb/Symbol/ObjectFile.h" -#include "llvm/Object/Binary.h" - -class ObjectFilePECOFF : public lldb_private::ObjectFile { -public: - typedef enum MachineType { - MachineUnknown = 0x0, - MachineAm33 = 0x1d3, - MachineAmd64 = 0x8664, - MachineArm = 0x1c0, - MachineArmNt = 0x1c4, - MachineArm64 = 0xaa64, - MachineEbc = 0xebc, - MachineX86 = 0x14c, - MachineIA64 = 0x200, - MachineM32R = 0x9041, - MachineMips16 = 0x266, - MachineMipsFpu = 0x366, - MachineMipsFpu16 = 0x466, - MachinePowerPc = 0x1f0, - MachinePowerPcfp = 0x1f1, - MachineR4000 = 0x166, - MachineSh3 = 0x1a2, - MachineSh3dsp = 0x1a3, - MachineSh4 = 0x1a6, - MachineSh5 = 0x1a8, - MachineThumb = 0x1c2, - MachineWcemIpsv2 = 0x169 - } MachineType; - - ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - const lldb_private::FileSpec *file, - lldb::offset_t file_offset, lldb::offset_t length); - - ObjectFilePECOFF(const lldb::ModuleSP &module_sp, - lldb::DataBufferSP &header_data_sp, - const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); - - ~ObjectFilePECOFF() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static ObjectFile * - CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, const lldb_private::FileSpec *file, - lldb::offset_t offset, lldb::offset_t length); - - static lldb_private::ObjectFile *CreateMemoryInstance( - const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, - const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); - - static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, - lldb::DataBufferSP &data_sp, - lldb::offset_t data_offset, - lldb::offset_t file_offset, - lldb::offset_t length, - lldb_private::ModuleSpecList &specs); - - static bool SaveCore(const lldb::ProcessSP &process_sp, - const lldb_private::FileSpec &outfile, - lldb_private::Status &error); - - static bool MagicBytesMatch(lldb::DataBufferSP &data_sp); - - static lldb::SymbolType MapSymbolType(uint16_t coff_symbol_type); - - bool ParseHeader() override; - - bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, - bool value_is_offset) override; - - lldb::ByteOrder GetByteOrder() const override; - - bool IsExecutable() const override; - - uint32_t GetAddressByteSize() const override; - - // virtual lldb_private::AddressClass - // GetAddressClass (lldb::addr_t file_addr); - - lldb_private::Symtab *GetSymtab() override; - - bool IsStripped() override; - - void CreateSections(lldb_private::SectionList &unified_section_list) override; - - void Dump(lldb_private::Stream *s) override; - - lldb_private::ArchSpec GetArchitecture() override; - - bool GetUUID(lldb_private::UUID *uuid) override; - - uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; - - virtual lldb_private::Address GetEntryPointAddress() override; - - ObjectFile::Type CalculateType() override; - - ObjectFile::Strata CalculateStrata() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - - bool IsWindowsSubsystem(); - - lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size); - -protected: - bool NeedsEndianSwap() const; - - typedef struct dos_header { // DOS .EXE header - uint16_t e_magic; // Magic number - uint16_t e_cblp; // Bytes on last page of file - uint16_t e_cp; // Pages in file - uint16_t e_crlc; // Relocations - uint16_t e_cparhdr; // Size of header in paragraphs - uint16_t e_minalloc; // Minimum extra paragraphs needed - uint16_t e_maxalloc; // Maximum extra paragraphs needed - uint16_t e_ss; // Initial (relative) SS value - uint16_t e_sp; // Initial SP value - uint16_t e_csum; // Checksum - uint16_t e_ip; // Initial IP value - uint16_t e_cs; // Initial (relative) CS value - uint16_t e_lfarlc; // File address of relocation table - uint16_t e_ovno; // Overlay number - uint16_t e_res[4]; // Reserved words - uint16_t e_oemid; // OEM identifier (for e_oeminfo) - uint16_t e_oeminfo; // OEM information; e_oemid specific - uint16_t e_res2[10]; // Reserved words - uint32_t e_lfanew; // File address of new exe header - } dos_header_t; - - typedef struct coff_header { - uint16_t machine; - uint16_t nsects; - uint32_t modtime; - uint32_t symoff; - uint32_t nsyms; - uint16_t hdrsize; - uint16_t flags; - } coff_header_t; - - typedef struct data_directory { - uint32_t vmaddr; - uint32_t vmsize; - } data_directory_t; - - typedef struct coff_opt_header { - uint16_t magic; - uint8_t major_linker_version; - uint8_t minor_linker_version; - uint32_t code_size; - uint32_t data_size; - uint32_t bss_size; - uint32_t entry; - uint32_t code_offset; - uint32_t data_offset; - - uint64_t image_base; - uint32_t sect_alignment; - uint32_t file_alignment; - uint16_t major_os_system_version; - uint16_t minor_os_system_version; - uint16_t major_image_version; - uint16_t minor_image_version; - uint16_t major_subsystem_version; - uint16_t minor_subsystem_version; - uint32_t reserved1; - uint32_t image_size; - uint32_t header_size; - uint32_t checksum; - uint16_t subsystem; - uint16_t dll_flags; - uint64_t stack_reserve_size; - uint64_t stack_commit_size; - uint64_t heap_reserve_size; - uint64_t heap_commit_size; - uint32_t loader_flags; - // uint32_t num_data_dir_entries; - std::vector<data_directory> - data_dirs; // will contain num_data_dir_entries entries - } coff_opt_header_t; - - typedef enum coff_data_dir_type { - coff_data_dir_export_table = 0, - coff_data_dir_import_table = 1, - } coff_data_dir_type; - - typedef struct section_header { - char name[8]; - uint32_t vmsize; // Virtual Size - uint32_t vmaddr; // Virtual Addr - uint32_t size; // File size - uint32_t offset; // File offset - uint32_t reloff; // Offset to relocations - uint32_t lineoff; // Offset to line table entries - uint16_t nreloc; // Number of relocation entries - uint16_t nline; // Number of line table entries - uint32_t flags; - } section_header_t; - - typedef struct coff_symbol { - char name[8]; - uint32_t value; - uint16_t sect; - uint16_t type; - uint8_t storage; - uint8_t naux; - } coff_symbol_t; - - typedef struct export_directory_entry { - uint32_t characteristics; - uint32_t time_date_stamp; - uint16_t major_version; - uint16_t minor_version; - uint32_t name; - uint32_t base; - uint32_t number_of_functions; - uint32_t number_of_names; - uint32_t address_of_functions; - uint32_t address_of_names; - uint32_t address_of_name_ordinals; - } export_directory_entry; - - static bool ParseDOSHeader(lldb_private::DataExtractor &data, - dos_header_t &dos_header); - static bool ParseCOFFHeader(lldb_private::DataExtractor &data, - lldb::offset_t *offset_ptr, - coff_header_t &coff_header); - bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr); - bool ParseSectionHeaders(uint32_t offset); - - uint32_t ParseDependentModules(); - - static void DumpDOSHeader(lldb_private::Stream *s, - const dos_header_t &header); - static void DumpCOFFHeader(lldb_private::Stream *s, - const coff_header_t &header); - static void DumpOptCOFFHeader(lldb_private::Stream *s, - const coff_opt_header_t &header); - void DumpSectionHeaders(lldb_private::Stream *s); - void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh); - void DumpDependentModules(lldb_private::Stream *s); - - llvm::StringRef GetSectionName(const section_header_t §); - - typedef std::vector<section_header_t> SectionHeaderColl; - typedef SectionHeaderColl::iterator SectionHeaderCollIter; - typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; - -private: - bool CreateBinary(); - -private: - dos_header_t m_dos_header; - coff_header_t m_coff_header; - coff_opt_header_t m_coff_header_opt; - SectionHeaderColl m_sect_headers; - lldb::addr_t m_image_base; - lldb_private::Address m_entry_point_address; - llvm::Optional<lldb_private::FileSpecList> m_deps_filespec; - typedef llvm::object::OwningBinary<llvm::object::Binary> OWNBINType; - llvm::Optional<OWNBINType> m_owningbin; -}; - -#endif // liblldb_ObjectFilePECOFF_h_ diff --git a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp deleted file mode 100644 index e77888c871b55..0000000000000 --- a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//===-- WindowsMiniDump.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This function is separated out from ObjectFilePECOFF.cpp to name avoid name -// collisions with WinAPI preprocessor macros. - -#include "WindowsMiniDump.h" -#include "lldb/Utility/FileSpec.h" -#include "llvm/Support/ConvertUTF.h" - -#ifdef _WIN32 -#include "lldb/Host/windows/windows.h" -#include <dbghelp.h> -#endif - -namespace lldb_private { - -bool SaveMiniDump(const lldb::ProcessSP &process_sp, - const lldb_private::FileSpec &outfile, - lldb_private::Status &error) { - if (!process_sp) - return false; -#ifdef _WIN32 - HANDLE process_handle = ::OpenProcess( - PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_sp->GetID()); - const std::string file_name = outfile.GetCString(); - std::wstring wide_name; - wide_name.resize(file_name.size() + 1); - char *result_ptr = reinterpret_cast<char *>(&wide_name[0]); - const llvm::UTF8 *error_ptr = nullptr; - if (!llvm::ConvertUTF8toWide(sizeof(wchar_t), file_name, result_ptr, - error_ptr)) { - error.SetErrorString("cannot convert file name"); - return false; - } - HANDLE file_handle = - ::CreateFileW(wide_name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - const auto result = - ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle, - MiniDumpWithFullMemoryInfo, NULL, NULL, NULL); - ::CloseHandle(file_handle); - ::CloseHandle(process_handle); - if (!result) { - error.SetError(::GetLastError(), lldb::eErrorTypeWin32); - return false; - } - return true; -#endif - return false; -} - -} // namesapce lldb_private diff --git a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h deleted file mode 100644 index 135d533873876..0000000000000 --- a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.h +++ /dev/null @@ -1,23 +0,0 @@ -//===-- WindowsMiniDump.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_WindowsMiniDump_h_ -#define liblldb_WindowsMiniDump_h_ - -#include "lldb/Target/Process.h" - -namespace lldb_private { - -bool SaveMiniDump(const lldb::ProcessSP &process_sp, - const lldb_private::FileSpec &outfile, - lldb_private::Status &error); - -} // namespace lldb_private - -#endif diff --git a/source/Plugins/OperatingSystem/CMakeLists.txt b/source/Plugins/OperatingSystem/CMakeLists.txt deleted file mode 100644 index 655007a0aab9e..0000000000000 --- a/source/Plugins/OperatingSystem/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(Python) diff --git a/source/Plugins/OperatingSystem/Python/CMakeLists.txt b/source/Plugins/OperatingSystem/Python/CMakeLists.txt deleted file mode 100644 index e8b0f31d37363..0000000000000 --- a/source/Plugins/OperatingSystem/Python/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginOSPython PLUGIN - OperatingSystemPython.cpp - - LINK_LIBS - lldbCore - lldbInterpreter - lldbSymbol - lldbTarget - lldbPluginProcessUtility - ) diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp deleted file mode 100644 index 0ad30a528954b..0000000000000 --- a/source/Plugins/Platform/Android/AdbClient.cpp +++ /dev/null @@ -1,653 +0,0 @@ -//===-- AdbClient.cpp -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AdbClient.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/FileUtilities.h" - -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/PosixApi.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataEncoder.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timeout.h" - -#include <limits.h> - -#include <algorithm> -#include <cstdlib> -#include <fstream> -#include <sstream> - -// On Windows, transitive dependencies pull in <Windows.h>, which defines a -// macro that clashes with a method name. -#ifdef SendMessage -#undef SendMessage -#endif - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::platform_android; -using namespace std::chrono; - -namespace { - -const seconds kReadTimeout(20); -const char *kOKAY = "OKAY"; -const char *kFAIL = "FAIL"; -const char *kDATA = "DATA"; -const char *kDONE = "DONE"; - -const char *kSEND = "SEND"; -const char *kRECV = "RECV"; -const char *kSTAT = "STAT"; - -const size_t kSyncPacketLen = 8; -// Maximum size of a filesync DATA packet. -const size_t kMaxPushData = 2 * 1024; -// Default mode for pushed files. -const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG - -const char *kSocketNamespaceAbstract = "localabstract"; -const char *kSocketNamespaceFileSystem = "localfilesystem"; - -Status ReadAllBytes(Connection &conn, void *buffer, size_t size) { - - Status error; - ConnectionStatus status; - char *read_buffer = static_cast<char *>(buffer); - - auto now = steady_clock::now(); - const auto deadline = now + kReadTimeout; - size_t total_read_bytes = 0; - while (total_read_bytes < size && now < deadline) { - auto read_bytes = - conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, - duration_cast<microseconds>(deadline - now), status, &error); - if (error.Fail()) - return error; - total_read_bytes += read_bytes; - if (status != eConnectionStatusSuccess) - break; - now = steady_clock::now(); - } - if (total_read_bytes < size) - error = Status( - "Unable to read requested number of bytes. Connection status: %d.", - status); - return error; -} - -} // namespace - -Status AdbClient::CreateByDeviceID(const std::string &device_id, - AdbClient &adb) { - DeviceIDList connect_devices; - auto error = adb.GetDevices(connect_devices); - if (error.Fail()) - return error; - - std::string android_serial; - if (!device_id.empty()) - android_serial = device_id; - else if (const char *env_serial = std::getenv("ANDROID_SERIAL")) - android_serial = env_serial; - - if (android_serial.empty()) { - if (connect_devices.size() != 1) - return Status("Expected a single connected device, got instead %zu - try " - "setting 'ANDROID_SERIAL'", - connect_devices.size()); - adb.SetDeviceID(connect_devices.front()); - } else { - auto find_it = std::find(connect_devices.begin(), connect_devices.end(), - android_serial); - if (find_it == connect_devices.end()) - return Status("Device \"%s\" not found", android_serial.c_str()); - - adb.SetDeviceID(*find_it); - } - return error; -} - -AdbClient::AdbClient() {} - -AdbClient::AdbClient(const std::string &device_id) : m_device_id(device_id) {} - -AdbClient::~AdbClient() {} - -void AdbClient::SetDeviceID(const std::string &device_id) { - m_device_id = device_id; -} - -const std::string &AdbClient::GetDeviceID() const { return m_device_id; } - -Status AdbClient::Connect() { - Status error; - m_conn.reset(new ConnectionFileDescriptor); - m_conn->Connect("connect://localhost:5037", &error); - - return error; -} - -Status AdbClient::GetDevices(DeviceIDList &device_list) { - device_list.clear(); - - auto error = SendMessage("host:devices"); - if (error.Fail()) - return error; - - error = ReadResponseStatus(); - if (error.Fail()) - return error; - - std::vector<char> in_buffer; - error = ReadMessage(in_buffer); - - llvm::StringRef response(&in_buffer[0], in_buffer.size()); - llvm::SmallVector<llvm::StringRef, 4> devices; - response.split(devices, "\n", -1, false); - - for (const auto device : devices) - device_list.push_back(device.split('\t').first); - - // Force disconnect since ADB closes connection after host:devices response - // is sent. - m_conn.reset(); - return error; -} - -Status AdbClient::SetPortForwarding(const uint16_t local_port, - const uint16_t remote_port) { - char message[48]; - snprintf(message, sizeof(message), "forward:tcp:%d;tcp:%d", local_port, - remote_port); - - const auto error = SendDeviceMessage(message); - if (error.Fail()) - return error; - - return ReadResponseStatus(); -} - -Status -AdbClient::SetPortForwarding(const uint16_t local_port, - llvm::StringRef remote_socket_name, - const UnixSocketNamespace socket_namespace) { - char message[PATH_MAX]; - const char *sock_namespace_str = - (socket_namespace == UnixSocketNamespaceAbstract) - ? kSocketNamespaceAbstract - : kSocketNamespaceFileSystem; - snprintf(message, sizeof(message), "forward:tcp:%d;%s:%s", local_port, - sock_namespace_str, remote_socket_name.str().c_str()); - - const auto error = SendDeviceMessage(message); - if (error.Fail()) - return error; - - return ReadResponseStatus(); -} - -Status AdbClient::DeletePortForwarding(const uint16_t local_port) { - char message[32]; - snprintf(message, sizeof(message), "killforward:tcp:%d", local_port); - - const auto error = SendDeviceMessage(message); - if (error.Fail()) - return error; - - return ReadResponseStatus(); -} - -Status AdbClient::SendMessage(const std::string &packet, const bool reconnect) { - Status error; - if (!m_conn || reconnect) { - error = Connect(); - if (error.Fail()) - return error; - } - - char length_buffer[5]; - snprintf(length_buffer, sizeof(length_buffer), "%04x", - static_cast<int>(packet.size())); - - ConnectionStatus status; - - m_conn->Write(length_buffer, 4, status, &error); - if (error.Fail()) - return error; - - m_conn->Write(packet.c_str(), packet.size(), status, &error); - return error; -} - -Status AdbClient::SendDeviceMessage(const std::string &packet) { - std::ostringstream msg; - msg << "host-serial:" << m_device_id << ":" << packet; - return SendMessage(msg.str()); -} - -Status AdbClient::ReadMessage(std::vector<char> &message) { - message.clear(); - - char buffer[5]; - buffer[4] = 0; - - auto error = ReadAllBytes(buffer, 4); - if (error.Fail()) - return error; - - unsigned int packet_len = 0; - sscanf(buffer, "%x", &packet_len); - - message.resize(packet_len, 0); - error = ReadAllBytes(&message[0], packet_len); - if (error.Fail()) - message.clear(); - - return error; -} - -Status AdbClient::ReadMessageStream(std::vector<char> &message, - milliseconds timeout) { - auto start = steady_clock::now(); - message.clear(); - - Status error; - lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; - char buffer[1024]; - while (error.Success() && status == lldb::eConnectionStatusSuccess) { - auto end = steady_clock::now(); - auto elapsed = end - start; - if (elapsed >= timeout) - return Status("Timed out"); - - size_t n = m_conn->Read(buffer, sizeof(buffer), - duration_cast<microseconds>(timeout - elapsed), - status, &error); - if (n > 0) - message.insert(message.end(), &buffer[0], &buffer[n]); - } - return error; -} - -Status AdbClient::ReadResponseStatus() { - char response_id[5]; - - static const size_t packet_len = 4; - response_id[packet_len] = 0; - - auto error = ReadAllBytes(response_id, packet_len); - if (error.Fail()) - return error; - - if (strncmp(response_id, kOKAY, packet_len) != 0) - return GetResponseError(response_id); - - return error; -} - -Status AdbClient::GetResponseError(const char *response_id) { - if (strcmp(response_id, kFAIL) != 0) - return Status("Got unexpected response id from adb: \"%s\"", response_id); - - std::vector<char> error_message; - auto error = ReadMessage(error_message); - if (error.Success()) - error.SetErrorString( - std::string(&error_message[0], error_message.size()).c_str()); - - return error; -} - -Status AdbClient::SwitchDeviceTransport() { - std::ostringstream msg; - msg << "host:transport:" << m_device_id; - - auto error = SendMessage(msg.str()); - if (error.Fail()) - return error; - - return ReadResponseStatus(); -} - -Status AdbClient::StartSync() { - auto error = SwitchDeviceTransport(); - if (error.Fail()) - return Status("Failed to switch to device transport: %s", - error.AsCString()); - - error = Sync(); - if (error.Fail()) - return Status("Sync failed: %s", error.AsCString()); - - return error; -} - -Status AdbClient::Sync() { - auto error = SendMessage("sync:", false); - if (error.Fail()) - return error; - - return ReadResponseStatus(); -} - -Status AdbClient::ReadAllBytes(void *buffer, size_t size) { - return ::ReadAllBytes(*m_conn, buffer, size); -} - -Status AdbClient::internalShell(const char *command, milliseconds timeout, - std::vector<char> &output_buf) { - output_buf.clear(); - - auto error = SwitchDeviceTransport(); - if (error.Fail()) - return Status("Failed to switch to device transport: %s", - error.AsCString()); - - StreamString adb_command; - adb_command.Printf("shell:%s", command); - error = SendMessage(adb_command.GetString(), false); - if (error.Fail()) - return error; - - error = ReadResponseStatus(); - if (error.Fail()) - return error; - - error = ReadMessageStream(output_buf, timeout); - if (error.Fail()) - return error; - - // ADB doesn't propagate return code of shell execution - if - // output starts with /system/bin/sh: most likely command failed. - static const char *kShellPrefix = "/system/bin/sh:"; - if (output_buf.size() > strlen(kShellPrefix)) { - if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix))) - return Status("Shell command %s failed: %s", command, - std::string(output_buf.begin(), output_buf.end()).c_str()); - } - - return Status(); -} - -Status AdbClient::Shell(const char *command, milliseconds timeout, - std::string *output) { - std::vector<char> output_buffer; - auto error = internalShell(command, timeout, output_buffer); - if (error.Fail()) - return error; - - if (output) - output->assign(output_buffer.begin(), output_buffer.end()); - return error; -} - -Status AdbClient::ShellToFile(const char *command, milliseconds timeout, - const FileSpec &output_file_spec) { - std::vector<char> output_buffer; - auto error = internalShell(command, timeout, output_buffer); - if (error.Fail()) - return error; - - const auto output_filename = output_file_spec.GetPath(); - std::error_code EC; - llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::F_None); - if (EC) - return Status("Unable to open local file %s", output_filename.c_str()); - - dst.write(&output_buffer[0], output_buffer.size()); - dst.close(); - if (dst.has_error()) - return Status("Failed to write file %s", output_filename.c_str()); - return Status(); -} - -std::unique_ptr<AdbClient::SyncService> -AdbClient::GetSyncService(Status &error) { - std::unique_ptr<SyncService> sync_service; - error = StartSync(); - if (error.Success()) - sync_service.reset(new SyncService(std::move(m_conn))); - - return sync_service; -} - -Status AdbClient::SyncService::internalPullFile(const FileSpec &remote_file, - const FileSpec &local_file) { - const auto local_file_path = local_file.GetPath(); - llvm::FileRemover local_file_remover(local_file_path); - - std::error_code EC; - llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::F_None); - if (EC) - return Status("Unable to open local file %s", local_file_path.c_str()); - - const auto remote_file_path = remote_file.GetPath(false); - auto error = SendSyncRequest(kRECV, remote_file_path.length(), - remote_file_path.c_str()); - if (error.Fail()) - return error; - - std::vector<char> chunk; - bool eof = false; - while (!eof) { - error = PullFileChunk(chunk, eof); - if (error.Fail()) - return error; - if (!eof) - dst.write(&chunk[0], chunk.size()); - } - dst.close(); - if (dst.has_error()) - return Status("Failed to write file %s", local_file_path.c_str()); - - local_file_remover.releaseFile(); - return error; -} - -Status AdbClient::SyncService::internalPushFile(const FileSpec &local_file, - const FileSpec &remote_file) { - const auto local_file_path(local_file.GetPath()); - std::ifstream src(local_file_path.c_str(), std::ios::in | std::ios::binary); - if (!src.is_open()) - return Status("Unable to open local file %s", local_file_path.c_str()); - - std::stringstream file_description; - file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode; - std::string file_description_str = file_description.str(); - auto error = SendSyncRequest(kSEND, file_description_str.length(), - file_description_str.c_str()); - if (error.Fail()) - return error; - - char chunk[kMaxPushData]; - while (!src.eof() && !src.read(chunk, kMaxPushData).bad()) { - size_t chunk_size = src.gcount(); - error = SendSyncRequest(kDATA, chunk_size, chunk); - if (error.Fail()) - return Status("Failed to send file chunk: %s", error.AsCString()); - } - error = SendSyncRequest( - kDONE, llvm::sys::toTimeT(FileSystem::Instance().GetModificationTime(local_file)), - nullptr); - if (error.Fail()) - return error; - - std::string response_id; - uint32_t data_len; - error = ReadSyncHeader(response_id, data_len); - if (error.Fail()) - return Status("Failed to read DONE response: %s", error.AsCString()); - if (response_id == kFAIL) { - std::string error_message(data_len, 0); - error = ReadAllBytes(&error_message[0], data_len); - if (error.Fail()) - return Status("Failed to read DONE error message: %s", error.AsCString()); - return Status("Failed to push file: %s", error_message.c_str()); - } else if (response_id != kOKAY) - return Status("Got unexpected DONE response: %s", response_id.c_str()); - - // If there was an error reading the source file, finish the adb file - // transfer first so that adb isn't expecting any more data. - if (src.bad()) - return Status("Failed read on %s", local_file_path.c_str()); - return error; -} - -Status AdbClient::SyncService::internalStat(const FileSpec &remote_file, - uint32_t &mode, uint32_t &size, - uint32_t &mtime) { - const std::string remote_file_path(remote_file.GetPath(false)); - auto error = SendSyncRequest(kSTAT, remote_file_path.length(), - remote_file_path.c_str()); - if (error.Fail()) - return Status("Failed to send request: %s", error.AsCString()); - - static const size_t stat_len = strlen(kSTAT); - static const size_t response_len = stat_len + (sizeof(uint32_t) * 3); - - std::vector<char> buffer(response_len); - error = ReadAllBytes(&buffer[0], buffer.size()); - if (error.Fail()) - return Status("Failed to read response: %s", error.AsCString()); - - DataExtractor extractor(&buffer[0], buffer.size(), eByteOrderLittle, - sizeof(void *)); - offset_t offset = 0; - - const void *command = extractor.GetData(&offset, stat_len); - if (!command) - return Status("Failed to get response command"); - const char *command_str = static_cast<const char *>(command); - if (strncmp(command_str, kSTAT, stat_len)) - return Status("Got invalid stat command: %s", command_str); - - mode = extractor.GetU32(&offset); - size = extractor.GetU32(&offset); - mtime = extractor.GetU32(&offset); - return Status(); -} - -Status AdbClient::SyncService::PullFile(const FileSpec &remote_file, - const FileSpec &local_file) { - return executeCommand([this, &remote_file, &local_file]() { - return internalPullFile(remote_file, local_file); - }); -} - -Status AdbClient::SyncService::PushFile(const FileSpec &local_file, - const FileSpec &remote_file) { - return executeCommand([this, &local_file, &remote_file]() { - return internalPushFile(local_file, remote_file); - }); -} - -Status AdbClient::SyncService::Stat(const FileSpec &remote_file, uint32_t &mode, - uint32_t &size, uint32_t &mtime) { - return executeCommand([this, &remote_file, &mode, &size, &mtime]() { - return internalStat(remote_file, mode, size, mtime); - }); -} - -bool AdbClient::SyncService::IsConnected() const { - return m_conn && m_conn->IsConnected(); -} - -AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn) - : m_conn(std::move(conn)) {} - -Status -AdbClient::SyncService::executeCommand(const std::function<Status()> &cmd) { - if (!m_conn) - return Status("SyncService is disconnected"); - - const auto error = cmd(); - if (error.Fail()) - m_conn.reset(); - - return error; -} - -AdbClient::SyncService::~SyncService() {} - -Status AdbClient::SyncService::SendSyncRequest(const char *request_id, - const uint32_t data_len, - const void *data) { - const DataBufferSP data_sp(new DataBufferHeap(kSyncPacketLen, 0)); - DataEncoder encoder(data_sp, eByteOrderLittle, sizeof(void *)); - auto offset = encoder.PutData(0, request_id, strlen(request_id)); - encoder.PutU32(offset, data_len); - - Status error; - ConnectionStatus status; - m_conn->Write(data_sp->GetBytes(), kSyncPacketLen, status, &error); - if (error.Fail()) - return error; - - if (data) - m_conn->Write(data, data_len, status, &error); - return error; -} - -Status AdbClient::SyncService::ReadSyncHeader(std::string &response_id, - uint32_t &data_len) { - char buffer[kSyncPacketLen]; - - auto error = ReadAllBytes(buffer, kSyncPacketLen); - if (error.Success()) { - response_id.assign(&buffer[0], 4); - DataExtractor extractor(&buffer[4], 4, eByteOrderLittle, sizeof(void *)); - offset_t offset = 0; - data_len = extractor.GetU32(&offset); - } - - return error; -} - -Status AdbClient::SyncService::PullFileChunk(std::vector<char> &buffer, - bool &eof) { - buffer.clear(); - - std::string response_id; - uint32_t data_len; - auto error = ReadSyncHeader(response_id, data_len); - if (error.Fail()) - return error; - - if (response_id == kDATA) { - buffer.resize(data_len, 0); - error = ReadAllBytes(&buffer[0], data_len); - if (error.Fail()) - buffer.clear(); - } else if (response_id == kDONE) { - eof = true; - } else if (response_id == kFAIL) { - std::string error_message(data_len, 0); - error = ReadAllBytes(&error_message[0], data_len); - if (error.Fail()) - return Status("Failed to read pull error message: %s", error.AsCString()); - return Status("Failed to pull file: %s", error_message.c_str()); - } else - return Status("Pull failed with unknown response: %s", response_id.c_str()); - - return Status(); -} - -Status AdbClient::SyncService::ReadAllBytes(void *buffer, size_t size) { - return ::ReadAllBytes(*m_conn, buffer, size); -} diff --git a/source/Plugins/Platform/Android/AdbClient.h b/source/Plugins/Platform/Android/AdbClient.h deleted file mode 100644 index 0d2100fc5663b..0000000000000 --- a/source/Plugins/Platform/Android/AdbClient.h +++ /dev/null @@ -1,141 +0,0 @@ -//===-- AdbClient.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_AdbClient_h_ -#define liblldb_AdbClient_h_ - -#include "lldb/Utility/Status.h" -#include <chrono> -#include <functional> -#include <list> -#include <memory> -#include <string> -#include <vector> - -namespace lldb_private { - -class FileSpec; - -namespace platform_android { - -class AdbClient { -public: - enum UnixSocketNamespace { - UnixSocketNamespaceAbstract, - UnixSocketNamespaceFileSystem, - }; - - using DeviceIDList = std::list<std::string>; - - class SyncService { - friend class AdbClient; - - public: - ~SyncService(); - - Status PullFile(const FileSpec &remote_file, const FileSpec &local_file); - - Status PushFile(const FileSpec &local_file, const FileSpec &remote_file); - - Status Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size, - uint32_t &mtime); - - bool IsConnected() const; - - private: - explicit SyncService(std::unique_ptr<Connection> &&conn); - - Status SendSyncRequest(const char *request_id, const uint32_t data_len, - const void *data); - - Status ReadSyncHeader(std::string &response_id, uint32_t &data_len); - - Status PullFileChunk(std::vector<char> &buffer, bool &eof); - - Status ReadAllBytes(void *buffer, size_t size); - - Status internalPullFile(const FileSpec &remote_file, - const FileSpec &local_file); - - Status internalPushFile(const FileSpec &local_file, - const FileSpec &remote_file); - - Status internalStat(const FileSpec &remote_file, uint32_t &mode, - uint32_t &size, uint32_t &mtime); - - Status executeCommand(const std::function<Status()> &cmd); - - std::unique_ptr<Connection> m_conn; - }; - - static Status CreateByDeviceID(const std::string &device_id, AdbClient &adb); - - AdbClient(); - explicit AdbClient(const std::string &device_id); - - ~AdbClient(); - - const std::string &GetDeviceID() const; - - Status GetDevices(DeviceIDList &device_list); - - Status SetPortForwarding(const uint16_t local_port, - const uint16_t remote_port); - - Status SetPortForwarding(const uint16_t local_port, - llvm::StringRef remote_socket_name, - const UnixSocketNamespace socket_namespace); - - Status DeletePortForwarding(const uint16_t local_port); - - Status Shell(const char *command, std::chrono::milliseconds timeout, - std::string *output); - - Status ShellToFile(const char *command, std::chrono::milliseconds timeout, - const FileSpec &output_file_spec); - - std::unique_ptr<SyncService> GetSyncService(Status &error); - - Status SwitchDeviceTransport(); - -private: - Status Connect(); - - void SetDeviceID(const std::string &device_id); - - Status SendMessage(const std::string &packet, const bool reconnect = true); - - Status SendDeviceMessage(const std::string &packet); - - Status ReadMessage(std::vector<char> &message); - - Status ReadMessageStream(std::vector<char> &message, - std::chrono::milliseconds timeout); - - Status GetResponseError(const char *response_id); - - Status ReadResponseStatus(); - - Status Sync(); - - Status StartSync(); - - Status internalShell(const char *command, std::chrono::milliseconds timeout, - std::vector<char> &output_buf); - - Status ReadAllBytes(void *buffer, size_t size); - - std::string m_device_id; - std::unique_ptr<Connection> m_conn; -}; - -} // namespace platform_android -} // namespace lldb_private - -#endif // liblldb_AdbClient_h_ diff --git a/source/Plugins/Platform/Android/CMakeLists.txt b/source/Plugins/Platform/Android/CMakeLists.txt deleted file mode 100644 index 5abb51a0b94ac..0000000000000 --- a/source/Plugins/Platform/Android/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -add_lldb_library(lldbPluginPlatformAndroid PLUGIN - AdbClient.cpp - PlatformAndroid.cpp - PlatformAndroidRemoteGDBServer.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbPluginPlatformLinux - lldbPluginPlatformGDB - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp deleted file mode 100644 index a56ab0e301534..0000000000000 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ /dev/null @@ -1,398 +0,0 @@ -//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Core/Module.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Core/ValueObject.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/StringConvert.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Scalar.h" -#include "lldb/Utility/UriParser.h" - -#include "AdbClient.h" -#include "PlatformAndroid.h" -#include "PlatformAndroidRemoteGDBServer.h" -#include "lldb/Target/Target.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::platform_android; -using namespace std::chrono; - -static uint32_t g_initialize_count = 0; -static const unsigned int g_android_default_cache_size = - 2048; // Fits inside 4k adb packet. - -void PlatformAndroid::Initialize() { - PlatformLinux::Initialize(); - - if (g_initialize_count++ == 0) { -#if defined(__ANDROID__) - PlatformSP default_platform_sp(new PlatformAndroid(true)); - default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetHostPlatform(default_platform_sp); -#endif - PluginManager::RegisterPlugin( - PlatformAndroid::GetPluginNameStatic(false), - PlatformAndroid::GetPluginDescriptionStatic(false), - PlatformAndroid::CreateInstance); - } -} - -void PlatformAndroid::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance); - } - } - - PlatformLinux::Terminate(); -} - -PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, - force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::PC: - create = true; - break; - -#if defined(__ANDROID__) - // Only accept "unknown" for the vendor if the host is android and if - // "unknown" wasn't specified (it was just returned because it was NOT - // specified). - case llvm::Triple::VendorType::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; -#endif - default: - break; - } - - if (create) { - switch (triple.getEnvironment()) { - case llvm::Triple::Android: - break; - -#if defined(__ANDROID__) - // Only accept "unknown" for the OS if the host is android and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::EnvironmentType::UnknownEnvironment: - create = !arch->TripleEnvironmentWasSpecified(); - break; -#endif - default: - create = false; - break; - } - } - } - - if (create) { - if (log) - log->Printf("PlatformAndroid::%s() creating remote-android platform", - __FUNCTION__); - return PlatformSP(new PlatformAndroid(false)); - } - - if (log) - log->Printf( - "PlatformAndroid::%s() aborting creation of remote-android platform", - __FUNCTION__); - - return PlatformSP(); -} - -PlatformAndroid::PlatformAndroid(bool is_host) - : PlatformLinux(is_host), m_sdk_version(0) {} - -PlatformAndroid::~PlatformAndroid() {} - -ConstString PlatformAndroid::GetPluginNameStatic(bool is_host) { - if (is_host) { - static ConstString g_host_name(Platform::GetHostPlatformName()); - return g_host_name; - } else { - static ConstString g_remote_name("remote-android"); - return g_remote_name; - } -} - -const char *PlatformAndroid::GetPluginDescriptionStatic(bool is_host) { - if (is_host) - return "Local Android user platform plug-in."; - else - return "Remote Android user platform plug-in."; -} - -ConstString PlatformAndroid::GetPluginName() { - return GetPluginNameStatic(IsHost()); -} - -Status PlatformAndroid::ConnectRemote(Args &args) { - m_device_id.clear(); - - if (IsHost()) { - return Status("can't connect to the host platform '%s', always connected", - GetPluginName().GetCString()); - } - - if (!m_remote_platform_sp) - m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); - - int port; - llvm::StringRef scheme, host, path; - const char *url = args.GetArgumentAtIndex(0); - if (!url) - return Status("URL is null."); - if (!UriParser::Parse(url, scheme, host, port, path)) - return Status("Invalid URL: %s", url); - if (host != "localhost") - m_device_id = host; - - auto error = PlatformLinux::ConnectRemote(args); - if (error.Success()) { - AdbClient adb; - error = AdbClient::CreateByDeviceID(m_device_id, adb); - if (error.Fail()) - return error; - - m_device_id = adb.GetDeviceID(); - } - return error; -} - -Status PlatformAndroid::GetFile(const FileSpec &source, - const FileSpec &destination) { - if (IsHost() || !m_remote_platform_sp) - return PlatformLinux::GetFile(source, destination); - - FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix); - if (source_spec.IsRelative()) - source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( - source_spec.GetCString(false)); - - Status error; - auto sync_service = GetSyncService(error); - if (error.Fail()) - return error; - - uint32_t mode = 0, size = 0, mtime = 0; - error = sync_service->Stat(source_spec, mode, size, mtime); - if (error.Fail()) - return error; - - if (mode != 0) - return sync_service->PullFile(source_spec, destination); - - auto source_file = source_spec.GetCString(false); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", - source_file); - - if (strchr(source_file, '\'') != nullptr) - return Status("Doesn't support single-quotes in filenames"); - - // mode == 0 can signify that adbd cannot access the file due security - // constraints - try "cat ..." as a fallback. - AdbClient adb(m_device_id); - - char cmd[PATH_MAX]; - snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); - - return adb.ShellToFile(cmd, minutes(1), destination); -} - -Status PlatformAndroid::PutFile(const FileSpec &source, - const FileSpec &destination, uint32_t uid, - uint32_t gid) { - if (IsHost() || !m_remote_platform_sp) - return PlatformLinux::PutFile(source, destination, uid, gid); - - FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix); - if (destination_spec.IsRelative()) - destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( - destination_spec.GetCString(false)); - - // TODO: Set correct uid and gid on remote file. - Status error; - auto sync_service = GetSyncService(error); - if (error.Fail()) - return error; - return sync_service->PushFile(source, destination_spec); -} - -const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); } - -Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec, - const uint64_t src_offset, - const uint64_t src_size, - const FileSpec &dst_file_spec) { - if (src_offset != 0) - return Status("Invalid offset - %" PRIu64, src_offset); - - return GetFile(src_file_spec, dst_file_spec); -} - -Status PlatformAndroid::DisconnectRemote() { - Status error = PlatformLinux::DisconnectRemote(); - if (error.Success()) { - m_device_id.clear(); - m_sdk_version = 0; - } - return error; -} - -uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() { - return g_android_default_cache_size; -} - -uint32_t PlatformAndroid::GetSdkVersion() { - if (!IsConnected()) - return 0; - - if (m_sdk_version != 0) - return m_sdk_version; - - std::string version_string; - AdbClient adb(m_device_id); - Status error = - adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string); - version_string = llvm::StringRef(version_string).trim().str(); - - if (error.Fail() || version_string.empty()) { - Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("Get SDK version failed. (error: %s, output: %s)", - error.AsCString(), version_string.c_str()); - return 0; - } - - m_sdk_version = StringConvert::ToUInt32(version_string.c_str()); - return m_sdk_version; -} - -Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp, - const FileSpec &dst_file_spec) { - // For oat file we can try to fetch additional debug info from the device - ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); - if (extension != ConstString(".oat") && extension != ConstString(".odex")) - return Status( - "Symbol file downloading only supported for oat and odex files"); - - // If we have no information about the platform file we can't execute oatdump - if (!module_sp->GetPlatformFileSpec()) - return Status("No platform file specified"); - - // Symbolizer isn't available before SDK version 23 - if (GetSdkVersion() < 23) - return Status("Symbol file generation only supported on SDK 23+"); - - // If we already have symtab then we don't have to try and generate one - if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != - nullptr) - return Status("Symtab already available in the module"); - - AdbClient adb(m_device_id); - std::string tmpdir; - Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", - seconds(5), &tmpdir); - if (error.Fail() || tmpdir.empty()) - return Status("Failed to generate temporary directory on the device (%s)", - error.AsCString()); - tmpdir = llvm::StringRef(tmpdir).trim().str(); - - // Create file remover for the temporary directory created on the device - std::unique_ptr<std::string, std::function<void(std::string *)>> - tmpdir_remover(&tmpdir, [&adb](std::string *s) { - StreamString command; - command.Printf("rm -rf %s", s->c_str()); - Status error = adb.Shell(command.GetData(), seconds(5), nullptr); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log && error.Fail()) - log->Printf("Failed to remove temp directory: %s", error.AsCString()); - }); - - FileSpec symfile_platform_filespec(tmpdir); - symfile_platform_filespec.AppendPathComponent("symbolized.oat"); - - // Execute oatdump on the remote device to generate a file with symtab - StreamString command; - command.Printf("oatdump --symbolize=%s --output=%s", - module_sp->GetPlatformFileSpec().GetCString(false), - symfile_platform_filespec.GetCString(false)); - error = adb.Shell(command.GetData(), minutes(1), nullptr); - if (error.Fail()) - return Status("Oatdump failed: %s", error.AsCString()); - - // Download the symbolfile from the remote device - return GetFile(symfile_platform_filespec, dst_file_spec); -} - -bool PlatformAndroid::GetRemoteOSVersion() { - m_os_version = llvm::VersionTuple(GetSdkVersion()); - return !m_os_version.empty(); -} - -llvm::StringRef -PlatformAndroid::GetLibdlFunctionDeclarations(lldb_private::Process *process) { - SymbolContextList matching_symbols; - std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" }; - const char *dl_open_name = nullptr; - Target &target = process->GetTarget(); - for (auto name: dl_open_names) { - if (target.GetImages().FindFunctionSymbols(ConstString(name), - eFunctionNameTypeFull, - matching_symbols)) { - dl_open_name = name; - break; - } - } - // Older platform versions have the dl function symbols mangled - if (dl_open_name == dl_open_names[0]) - return R"( - extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); - extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); - extern "C" int dlclose(void*) asm("__dl_dlclose"); - extern "C" char* dlerror(void) asm("__dl_dlerror"); - )"; - - return PlatformPOSIX::GetLibdlFunctionDeclarations(process); -} - -AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { - if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) - return m_adb_sync_svc.get(); - - AdbClient adb(m_device_id); - m_adb_sync_svc = adb.GetSyncService(error); - return (error.Success()) ? m_adb_sync_svc.get() : nullptr; -} diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h deleted file mode 100644 index 2e7706cc246e0..0000000000000 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ /dev/null @@ -1,91 +0,0 @@ -//===-- PlatformAndroid.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformAndroid_h_ -#define liblldb_PlatformAndroid_h_ - -#include <memory> -#include <string> - -#include "Plugins/Platform/Linux/PlatformLinux.h" - -#include "AdbClient.h" - -namespace lldb_private { -namespace platform_android { - -class PlatformAndroid : public platform_linux::PlatformLinux { -public: - PlatformAndroid(bool is_host); - - ~PlatformAndroid() override; - - static void Initialize(); - - static void Terminate(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); - - static ConstString GetPluginNameStatic(bool is_host); - - static const char *GetPluginDescriptionStatic(bool is_host); - - ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - Status ConnectRemote(Args &args) override; - - Status GetFile(const FileSpec &source, const FileSpec &destination) override; - - Status PutFile(const FileSpec &source, const FileSpec &destination, - uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; - - uint32_t GetSdkVersion(); - - bool GetRemoteOSVersion() override; - - Status DisconnectRemote() override; - - uint32_t GetDefaultMemoryCacheLineSize() override; - -protected: - const char *GetCacheHostname() override; - - Status DownloadModuleSlice(const FileSpec &src_file_spec, - const uint64_t src_offset, const uint64_t src_size, - const FileSpec &dst_file_spec) override; - - Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, - const FileSpec &dst_file_spec) override; - - llvm::StringRef - GetLibdlFunctionDeclarations(lldb_private::Process *process) override; - -private: - AdbClient::SyncService *GetSyncService(Status &error); - - std::unique_ptr<AdbClient::SyncService> m_adb_sync_svc; - std::string m_device_id; - uint32_t m_sdk_version; - - DISALLOW_COPY_AND_ASSIGN(PlatformAndroid); -}; - -} // namespace platofor_android -} // namespace lldb_private - -#endif // liblldb_PlatformAndroid_h_ diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp deleted file mode 100644 index bbb03369d63c6..0000000000000 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ /dev/null @@ -1,232 +0,0 @@ -//===-- PlatformAndroidRemoteGDBServer.cpp ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/common/TCPSocket.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/UriParser.h" - -#include "PlatformAndroidRemoteGDBServer.h" - -#include <sstream> - -using namespace lldb; -using namespace lldb_private; -using namespace platform_android; - -static const lldb::pid_t g_remote_platform_pid = - 0; // Alias for the process id of lldb-platform - -static Status ForwardPortWithAdb( - const uint16_t local_port, const uint16_t remote_port, - llvm::StringRef remote_socket_name, - const llvm::Optional<AdbClient::UnixSocketNamespace> &socket_namespace, - std::string &device_id) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - - AdbClient adb; - auto error = AdbClient::CreateByDeviceID(device_id, adb); - if (error.Fail()) - return error; - - device_id = adb.GetDeviceID(); - if (log) - log->Printf("Connected to Android device \"%s\"", device_id.c_str()); - - if (remote_port != 0) { - if (log) - log->Printf("Forwarding remote TCP port %d to local TCP port %d", - remote_port, local_port); - return adb.SetPortForwarding(local_port, remote_port); - } - - if (log) - log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", - remote_socket_name.str().c_str(), local_port); - - if (!socket_namespace) - return Status("Invalid socket namespace"); - - return adb.SetPortForwarding(local_port, remote_socket_name, - *socket_namespace); -} - -static Status DeleteForwardPortWithAdb(uint16_t local_port, - const std::string &device_id) { - AdbClient adb(device_id); - return adb.DeletePortForwarding(local_port); -} - -static Status FindUnusedPort(uint16_t &port) { - Status error; - std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(true, false)); - if (error.Fail()) - return error; - - error = tcp_socket->Listen("127.0.0.1:0", 1); - if (error.Success()) - port = tcp_socket->GetLocalPortNumber(); - - return error; -} - -PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer() {} - -PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer() { - for (const auto &it : m_port_forwards) - DeleteForwardPortWithAdb(it.second, m_device_id); -} - -bool PlatformAndroidRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, - std::string &connect_url) { - uint16_t remote_port = 0; - std::string socket_name; - if (!m_gdb_client.LaunchGDBServer("127.0.0.1", pid, remote_port, socket_name)) - return false; - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - - auto error = - MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); - if (error.Success() && log) - log->Printf("gdbserver connect URL: %s", connect_url.c_str()); - - return error.Success(); -} - -bool PlatformAndroidRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { - DeleteForwardPort(pid); - return m_gdb_client.KillSpawnedProcess(pid); -} - -Status PlatformAndroidRemoteGDBServer::ConnectRemote(Args &args) { - m_device_id.clear(); - - if (args.GetArgumentCount() != 1) - return Status( - "\"platform connect\" takes a single argument: <connect-url>"); - - int remote_port; - llvm::StringRef scheme, host, path; - const char *url = args.GetArgumentAtIndex(0); - if (!url) - return Status("URL is null."); - if (!UriParser::Parse(url, scheme, host, remote_port, path)) - return Status("Invalid URL: %s", url); - if (host != "localhost") - m_device_id = host; - - m_socket_namespace.reset(); - if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME) - m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem; - else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME) - m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract; - - std::string connect_url; - auto error = - MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port, - path, connect_url); - - if (error.Fail()) - return error; - - args.ReplaceArgumentAtIndex(0, connect_url); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); - - error = PlatformRemoteGDBServer::ConnectRemote(args); - if (error.Fail()) - DeleteForwardPort(g_remote_platform_pid); - - return error; -} - -Status PlatformAndroidRemoteGDBServer::DisconnectRemote() { - DeleteForwardPort(g_remote_platform_pid); - return PlatformRemoteGDBServer::DisconnectRemote(); -} - -void PlatformAndroidRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - - auto it = m_port_forwards.find(pid); - if (it == m_port_forwards.end()) - return; - - const auto port = it->second; - const auto error = DeleteForwardPortWithAdb(port, m_device_id); - if (error.Fail()) { - if (log) - log->Printf("Failed to delete port forwarding (pid=%" PRIu64 - ", port=%d, device=%s): %s", - pid, port, m_device_id.c_str(), error.AsCString()); - } - m_port_forwards.erase(it); -} - -Status PlatformAndroidRemoteGDBServer::MakeConnectURL( - const lldb::pid_t pid, const uint16_t remote_port, - llvm::StringRef remote_socket_name, std::string &connect_url) { - static const int kAttempsNum = 5; - - Status error; - // There is a race possibility that somebody will occupy a port while we're - // in between FindUnusedPort and ForwardPortWithAdb - adding the loop to - // mitigate such problem. - for (auto i = 0; i < kAttempsNum; ++i) { - uint16_t local_port = 0; - error = FindUnusedPort(local_port); - if (error.Fail()) - return error; - - error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name, - m_socket_namespace, m_device_id); - if (error.Success()) { - m_port_forwards[pid] = local_port; - std::ostringstream url_str; - url_str << "connect://localhost:" << local_port; - connect_url = url_str.str(); - break; - } - } - - return error; -} - -lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess( - llvm::StringRef connect_url, llvm::StringRef plugin_name, - lldb_private::Debugger &debugger, lldb_private::Target *target, - lldb_private::Status &error) { - // We don't have the pid of the remote gdbserver when it isn't started by us - // but we still want to store the list of port forwards we set up in our port - // forward map. Generate a fake pid for these cases what won't collide with - // any other valid pid on android. - static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; - - int remote_port; - llvm::StringRef scheme, host, path; - if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) { - error.SetErrorStringWithFormat("Invalid URL: %s", - connect_url.str().c_str()); - return nullptr; - } - - std::string new_connect_url; - error = MakeConnectURL(s_remote_gdbserver_fake_pid--, - (remote_port < 0) ? 0 : remote_port, path, - new_connect_url); - if (error.Fail()) - return nullptr; - - return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, - debugger, target, error); -} diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h deleted file mode 100644 index 40356293b589a..0000000000000 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ /dev/null @@ -1,64 +0,0 @@ -//===-- PlatformAndroidRemoteGDBServer.h ------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformAndroidRemoteGDBServer_h_ -#define liblldb_PlatformAndroidRemoteGDBServer_h_ - -#include <map> -#include <utility> - -#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" - -#include "llvm/ADT/Optional.h" - -#include "AdbClient.h" - -namespace lldb_private { -namespace platform_android { - -class PlatformAndroidRemoteGDBServer - : public platform_gdb_server::PlatformRemoteGDBServer { -public: - PlatformAndroidRemoteGDBServer(); - - ~PlatformAndroidRemoteGDBServer() override; - - Status ConnectRemote(Args &args) override; - - Status DisconnectRemote() override; - - lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, - llvm::StringRef plugin_name, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Status &error) override; - -protected: - std::string m_device_id; - std::map<lldb::pid_t, uint16_t> m_port_forwards; - llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace; - - bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; - - bool KillSpawnedProcess(lldb::pid_t pid) override; - - void DeleteForwardPort(lldb::pid_t pid); - - Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, - llvm::StringRef remote_socket_name, - std::string &connect_url); - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformAndroidRemoteGDBServer); -}; - -} // namespace platform_android -} // namespace lldb_private - -#endif // liblldb_PlatformAndroidRemoteGDBServer_h_ diff --git a/source/Plugins/Platform/CMakeLists.txt b/source/Plugins/Platform/CMakeLists.txt deleted file mode 100644 index ddb71212ce48d..0000000000000 --- a/source/Plugins/Platform/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -#if (CMAKE_SYSTEM_NAME MATCHES "Linux") - add_subdirectory(Linux) -#elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - add_subdirectory(FreeBSD) -#elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") - add_subdirectory(NetBSD) -#elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") - add_subdirectory(OpenBSD) -#elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX) -#elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") - add_subdirectory(Windows) -#endif() - -add_subdirectory(POSIX) -add_subdirectory(gdb-server) -add_subdirectory(Kalimba) -add_subdirectory(Android) diff --git a/source/Plugins/Platform/FreeBSD/CMakeLists.txt b/source/Plugins/Platform/FreeBSD/CMakeLists.txt deleted file mode 100644 index 1c27e1b7adaaa..0000000000000 --- a/source/Plugins/Platform/FreeBSD/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginPlatformFreeBSD PLUGIN - PlatformFreeBSD.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbTarget - ) diff --git a/source/Plugins/Platform/Kalimba/CMakeLists.txt b/source/Plugins/Platform/Kalimba/CMakeLists.txt deleted file mode 100644 index 02f1827f9a485..0000000000000 --- a/source/Plugins/Platform/Kalimba/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_lldb_library(lldbPluginPlatformKalimba PLUGIN - PlatformKalimba.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbTarget - ) diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp b/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp deleted file mode 100644 index cc902b7f7ad52..0000000000000 --- a/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp +++ /dev/null @@ -1,154 +0,0 @@ -//===-- PlatformKalimba.cpp ---------------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformKalimba.h" -#include "lldb/Host/Config.h" - -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -static uint32_t g_initialize_count = 0; - -PlatformSP PlatformKalimba::CreateInstance(bool force, const ArchSpec *arch) { - bool create = force; - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::CSR: - create = true; - break; - - default: - break; - } - } - if (create) - return PlatformSP(new PlatformKalimba(false)); - return PlatformSP(); -} - -lldb_private::ConstString -PlatformKalimba::GetPluginNameStatic(bool /*is_host*/) { - static ConstString g_remote_name("kalimba"); - return g_remote_name; -} - -const char *PlatformKalimba::GetPluginDescriptionStatic(bool /*is_host*/) { - return "Kalimba user platform plug-in."; -} - -lldb_private::ConstString PlatformKalimba::GetPluginName() { - return GetPluginNameStatic(false); -} - -void PlatformKalimba::Initialize() { - Platform::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin( - PlatformKalimba::GetPluginNameStatic(false), - PlatformKalimba::GetPluginDescriptionStatic(false), - PlatformKalimba::CreateInstance); - } -} - -void PlatformKalimba::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformKalimba::CreateInstance); - } - } - - Platform::Terminate(); -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformKalimba::PlatformKalimba(bool is_host) - : Platform(is_host), // This is the local host platform - m_remote_platform_sp() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformKalimba::~PlatformKalimba() {} - -bool PlatformKalimba::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - if (idx == 0) { - arch = ArchSpec("kalimba3-csr-unknown"); - return true; - } - if (idx == 1) { - arch = ArchSpec("kalimba4-csr-unknown"); - return true; - } - if (idx == 2) { - arch = ArchSpec("kalimba5-csr-unknown"); - return true; - } - return false; -} - -void PlatformKalimba::GetStatus(Stream &strm) { Platform::GetStatus(strm); } - -size_t -PlatformKalimba::GetSoftwareBreakpointTrapOpcode(Target & /*target*/, - BreakpointSite * /*bp_site*/) { - // the target hardware does not support software breakpoints - return 0; -} - -Status PlatformKalimba::LaunchProcess(ProcessLaunchInfo &launch_info) { - Status error; - - if (IsHost()) { - error.SetErrorString("native execution is not possible"); - } else { - error.SetErrorString("the platform is not currently connected"); - } - return error; -} - -lldb::ProcessSP PlatformKalimba::Attach(ProcessAttachInfo &attach_info, - Debugger &debugger, Target *target, - Status &error) { - lldb::ProcessSP process_sp; - if (IsHost()) { - error.SetErrorString("native execution is not possible"); - } else { - if (m_remote_platform_sp) - process_sp = - m_remote_platform_sp->Attach(attach_info, debugger, target, error); - else - error.SetErrorString("the platform is not currently connected"); - } - return process_sp; -} - -void PlatformKalimba::CalculateTrapHandlerSymbolNames() { - // TODO Research this sometime. -} diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.h b/source/Plugins/Platform/Kalimba/PlatformKalimba.h deleted file mode 100644 index efa78457d5859..0000000000000 --- a/source/Plugins/Platform/Kalimba/PlatformKalimba.h +++ /dev/null @@ -1,75 +0,0 @@ -//===-- PlatformKalimba.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformKalimba_h_ -#define liblldb_PlatformKalimba_h_ - -#include "lldb/Target/Platform.h" - -namespace lldb_private { - -class PlatformKalimba : public Platform { -public: - PlatformKalimba(bool is_host); - - ~PlatformKalimba() override; - - static void Initialize(); - - static void Terminate(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static lldb_private::ConstString GetPluginNameStatic(bool is_host); - - static const char *GetPluginDescriptionStatic(bool is_host); - - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - const char *GetDescription() override { - return GetPluginDescriptionStatic(IsHost()); - } - - void GetStatus(Stream &strm) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override; - - size_t GetSoftwareBreakpointTrapOpcode(Target &target, - BreakpointSite *bp_site) override; - - lldb_private::Status - LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - - lldb::ProcessSP Attach(ProcessAttachInfo &attach_info, Debugger &debugger, - Target *target, Status &error) override; - - // Kalimba processes can not be launched by spawning and attaching. - bool CanDebugProcess() override { return false; } - - void CalculateTrapHandlerSymbolNames() override; - -protected: - lldb::PlatformSP m_remote_platform_sp; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformKalimba); -}; - -} // namespace lldb_private - -#endif // liblldb_PlatformKalimba_h_ diff --git a/source/Plugins/Platform/Linux/CMakeLists.txt b/source/Plugins/Platform/Linux/CMakeLists.txt deleted file mode 100644 index bad039d0ad509..0000000000000 --- a/source/Plugins/Platform/Linux/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_lldb_library(lldbPluginPlatformLinux PLUGIN - PlatformLinux.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbInterpreter - lldbTarget - lldbPluginPlatformPOSIX - ) diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp deleted file mode 100644 index 7498c648d6e4f..0000000000000 --- a/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ /dev/null @@ -1,408 +0,0 @@ -//===-- PlatformLinux.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformLinux.h" -#include "lldb/Host/Config.h" - -#include <stdio.h> -#ifndef LLDB_DISABLE_POSIX -#include <sys/utsname.h> -#endif - -#include "lldb/Core/Debugger.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -// Define these constants from Linux mman.h for use when targeting remote linux -// systems even when host has different values. -#define MAP_PRIVATE 2 -#define MAP_ANON 0x20 - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::platform_linux; - -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ - -PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, - arch ? arch->GetArchitectureName() : "<null>", - arch ? arch->GetTriple().getTriple() : "<null>"); - - bool create = force; - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getOS()) { - case llvm::Triple::Linux: - create = true; - break; - -#if defined(__linux__) - // Only accept "unknown" for the OS if the host is linux and it "unknown" - // wasn't specified (it was just returned because it was NOT specified) - case llvm::Triple::OSType::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif - default: - break; - } - } - - LLDB_LOG(log, "create = {0}", create); - if (create) { - return PlatformSP(new PlatformLinux(false)); - } - return PlatformSP(); -} - -ConstString PlatformLinux::GetPluginNameStatic(bool is_host) { - if (is_host) { - static ConstString g_host_name(Platform::GetHostPlatformName()); - return g_host_name; - } else { - static ConstString g_remote_name("remote-linux"); - return g_remote_name; - } -} - -const char *PlatformLinux::GetPluginDescriptionStatic(bool is_host) { - if (is_host) - return "Local Linux user platform plug-in."; - else - return "Remote Linux user platform plug-in."; -} - -ConstString PlatformLinux::GetPluginName() { - return GetPluginNameStatic(IsHost()); -} - -void PlatformLinux::Initialize() { - PlatformPOSIX::Initialize(); - - if (g_initialize_count++ == 0) { -#if defined(__linux__) && !defined(__ANDROID__) - PlatformSP default_platform_sp(new PlatformLinux(true)); - default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetHostPlatform(default_platform_sp); -#endif - PluginManager::RegisterPlugin( - PlatformLinux::GetPluginNameStatic(false), - PlatformLinux::GetPluginDescriptionStatic(false), - PlatformLinux::CreateInstance, nullptr); - } -} - -void PlatformLinux::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance); - } - } - - PlatformPOSIX::Terminate(); -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformLinux::PlatformLinux(bool is_host) - : PlatformPOSIX(is_host) // This is the local host platform -{} - -PlatformLinux::~PlatformLinux() = default; - -bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - if (IsHost()) { - ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - if (hostArch.GetTriple().isOSLinux()) { - if (idx == 0) { - arch = hostArch; - return arch.IsValid(); - } else if (idx == 1) { - // If the default host architecture is 64-bit, look for a 32-bit - // variant - if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { - arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); - return arch.IsValid(); - } - } - } - } else { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); - - llvm::Triple triple; - // Set the OS to linux - triple.setOS(llvm::Triple::Linux); - // Set the architecture - switch (idx) { - case 0: - triple.setArchName("x86_64"); - break; - case 1: - triple.setArchName("i386"); - break; - case 2: - triple.setArchName("arm"); - break; - case 3: - triple.setArchName("aarch64"); - break; - case 4: - triple.setArchName("mips64"); - break; - case 5: - triple.setArchName("hexagon"); - break; - case 6: - triple.setArchName("mips"); - break; - case 7: - triple.setArchName("mips64el"); - break; - case 8: - triple.setArchName("mipsel"); - break; - case 9: - triple.setArchName("s390x"); - break; - default: - return false; - } - // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the - // vendor by calling triple.SetVendorName("unknown") so that it is a - // "unspecified unknown". This means when someone calls - // triple.GetVendorName() it will return an empty string which indicates - // that the vendor can be set when two architectures are merged - - // Now set the triple into "arch" and return true - arch.SetTriple(triple); - return true; - } - return false; -} - -void PlatformLinux::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - -#ifndef LLDB_DISABLE_POSIX - // Display local kernel information only when we are running in host mode. - // Otherwise, we would end up printing non-Linux information (when running on - // Mac OS for example). - if (IsHost()) { - struct utsname un; - - if (uname(&un)) - return; - - strm.Printf(" Kernel: %s\n", un.sysname); - strm.Printf(" Release: %s\n", un.release); - strm.Printf(" Version: %s\n", un.version); - } -#endif -} - -int32_t -PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { - int32_t resume_count = 0; - - // Always resume past the initial stop when we use eLaunchFlagDebug - if (launch_info.GetFlags().Test(eLaunchFlagDebug)) { - // Resume past the stop for the final exec into the true inferior. - ++resume_count; - } - - // If we're not launching a shell, we're done. - const FileSpec &shell = launch_info.GetShell(); - if (!shell) - return resume_count; - - std::string shell_string = shell.GetPath(); - // We're in a shell, so for sure we have to resume past the shell exec. - ++resume_count; - - // Figure out what shell we're planning on using. - const char *shell_name = strrchr(shell_string.c_str(), '/'); - if (shell_name == NULL) - shell_name = shell_string.c_str(); - else - shell_name++; - - if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 || - strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) { - // These shells seem to re-exec themselves. Add another resume. - ++resume_count; - } - - return resume_count; -} - -bool PlatformLinux::CanDebugProcess() { - if (IsHost()) { - return true; - } else { - // If we're connected, we can debug. - return IsConnected(); - } -} - -// For local debugging, Linux will override the debug logic to use llgs-launch -// rather than lldb-launch, llgs-attach. This differs from current lldb- -// launch, debugserver-attach approach on MacOSX. -lldb::ProcessSP -PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, - Target *target, // Can be NULL, if NULL create a new - // target, else use existing one - Status &error) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - LLDB_LOG(log, "target {0}", target); - - // If we're a remote host, use standard behavior from parent class. - if (!IsHost()) - return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error); - - // - // For local debugging, we'll insist on having ProcessGDBRemote create the - // process. - // - - ProcessSP process_sp; - - // Make sure we stop at the entry point - launch_info.GetFlags().Set(eLaunchFlagDebug); - - // We always launch the process we are going to debug in a separate process - // group, since then we can handle ^C interrupts ourselves w/o having to - // worry about the target getting them as well. - launch_info.SetLaunchInSeparateProcessGroup(true); - - // Ensure we have a target. - if (target == nullptr) { - LLDB_LOG(log, "creating new target"); - TargetSP new_target_sp; - error = debugger.GetTargetList().CreateTarget( - debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); - if (error.Fail()) { - LLDB_LOG(log, "failed to create new target: {0}", error); - return process_sp; - } - - target = new_target_sp.get(); - if (!target) { - error.SetErrorString("CreateTarget() returned nullptr"); - LLDB_LOG(log, "error: {0}", error); - return process_sp; - } - } - - // Mark target as currently selected target. - debugger.GetTargetList().SetSelectedTarget(target); - - // Now create the gdb-remote process. - LLDB_LOG(log, "having target create process with gdb-remote plugin"); - process_sp = - target->CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr); - - if (!process_sp) { - error.SetErrorString("CreateProcess() failed for gdb-remote process"); - LLDB_LOG(log, "error: {0}", error); - return process_sp; - } - - LLDB_LOG(log, "successfully created process"); - // Adjust launch for a hijacker. - ListenerSP listener_sp; - if (!launch_info.GetHijackListener()) { - LLDB_LOG(log, "setting up hijacker"); - listener_sp = - Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); - launch_info.SetHijackListener(listener_sp); - process_sp->HijackProcessEvents(listener_sp); - } - - // Log file actions. - if (log) { - LLDB_LOG(log, "launching process with the following file actions:"); - StreamString stream; - size_t i = 0; - const FileAction *file_action; - while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { - file_action->Dump(stream); - LLDB_LOG(log, "{0}", stream.GetData()); - stream.Clear(); - } - } - - // Do the launch. - error = process_sp->Launch(launch_info); - if (error.Success()) { - // Handle the hijacking of process events. - if (listener_sp) { - const StateType state = process_sp->WaitForProcessToStop( - llvm::None, NULL, false, listener_sp); - - LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); - } - - // Hook up process PTY if we have one (which we should for local debugging - // with llgs). - int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != PseudoTerminal::invalid_fd) { - process_sp->SetSTDIOFileDescriptor(pty_fd); - LLDB_LOG(log, "hooked up STDIO pty to process"); - } else - LLDB_LOG(log, "not using process STDIO pty"); - } else { - LLDB_LOG(log, "process launch failed: {0}", error); - // FIXME figure out appropriate cleanup here. Do we delete the target? Do - // we delete the process? Does our caller do that? - } - - return process_sp; -} - -void PlatformLinux::CalculateTrapHandlerSymbolNames() { - m_trap_handlers.push_back(ConstString("_sigtramp")); -} - -MmapArgList PlatformLinux::GetMmapArgumentList(const ArchSpec &arch, - addr_t addr, addr_t length, - unsigned prot, unsigned flags, - addr_t fd, addr_t offset) { - uint64_t flags_platform = 0; - uint64_t map_anon = MAP_ANON; - - // To get correct flags for MIPS Architecture - if (arch.GetTriple().getArch() == llvm::Triple::mips64 || - arch.GetTriple().getArch() == llvm::Triple::mips64el || - arch.GetTriple().getArch() == llvm::Triple::mips || - arch.GetTriple().getArch() == llvm::Triple::mipsel) - map_anon = 0x800; - - if (flags & eMmapFlagsPrivate) - flags_platform |= MAP_PRIVATE; - if (flags & eMmapFlagsAnon) - flags_platform |= map_anon; - - MmapArgList args({addr, length, prot, flags_platform, fd, offset}); - return args; -} - diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h deleted file mode 100644 index 50d721f7c0723..0000000000000 --- a/source/Plugins/Platform/Linux/PlatformLinux.h +++ /dev/null @@ -1,74 +0,0 @@ -//===-- PlatformLinux.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformLinux_h_ -#define liblldb_PlatformLinux_h_ - -#include "Plugins/Platform/POSIX/PlatformPOSIX.h" - -namespace lldb_private { -namespace platform_linux { - -class PlatformLinux : public PlatformPOSIX { -public: - PlatformLinux(bool is_host); - - ~PlatformLinux() override; - - static void Initialize(); - - static void Terminate(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); - - static ConstString GetPluginNameStatic(bool is_host); - - static const char *GetPluginDescriptionStatic(bool is_host); - - ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - const char *GetDescription() override { - return GetPluginDescriptionStatic(IsHost()); - } - - void GetStatus(Stream &strm) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override; - - int32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override; - - bool CanDebugProcess() override; - - lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info, - Debugger &debugger, Target *target, - Status &error) override; - - void CalculateTrapHandlerSymbolNames() override; - - MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr, - lldb::addr_t length, unsigned prot, - unsigned flags, lldb::addr_t fd, - lldb::addr_t offset) override; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformLinux); -}; - -} // namespace platform_linux -} // namespace lldb_private - -#endif // liblldb_PlatformLinux_h_ diff --git a/source/Plugins/Platform/MacOSX/CMakeLists.txt b/source/Plugins/Platform/MacOSX/CMakeLists.txt deleted file mode 100644 index 6f0d952c35fb4..0000000000000 --- a/source/Plugins/Platform/MacOSX/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES - PlatformDarwin.cpp - PlatformDarwinKernel.cpp - PlatformMacOSX.cpp - PlatformRemoteiOS.cpp - PlatformRemoteAppleTV.cpp - PlatformRemoteAppleWatch.cpp - PlatformRemoteDarwinDevice.cpp - PlatformRemoteAppleBridge.cpp - ) - -list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES - PlatformAppleSimulator.cpp - PlatformiOSSimulator.cpp - PlatformAppleTVSimulator.cpp - PlatformAppleWatchSimulator.cpp - ) - -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") - include_directories(${LIBXML2_INCLUDE_DIR}) - add_subdirectory(objcxx) - set(OBJC_LIBS "lldbPluginPlatformMacOSXObjCXX") - list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES - ${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES}) -else() - list(APPEND LLVM_OPTIONAL_SOURCES - ${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES}) -endif() - -add_lldb_library(lldbPluginPlatformMacOSX PLUGIN - ${PLUGIN_PLATFORM_MACOSX_SOURCES} - - LINK_LIBS - clangBasic - lldbBreakpoint - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginPlatformPOSIX - ${OBJC_LIBS} - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp deleted file mode 100644 index a2f74a5fc8bc9..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp +++ /dev/null @@ -1,265 +0,0 @@ -//===-- PlatformAppleSimulator.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformAppleSimulator.h" - -#if defined(__APPLE__) -#include <dlfcn.h> -#endif - -#include <mutex> -#include <thread> -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" -#include "llvm/Support/Threading.h" - -using namespace lldb; -using namespace lldb_private; - -#if !defined(__APPLE__) -#define UNSUPPORTED_ERROR ("Apple simulators aren't supported on this platform") -#endif - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformAppleSimulator::Initialize() { PlatformDarwin::Initialize(); } - -void PlatformAppleSimulator::Terminate() { PlatformDarwin::Terminate(); } - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformAppleSimulator::PlatformAppleSimulator() - : PlatformDarwin(true), m_core_sim_path_mutex(), - m_core_simulator_framework_path(), m_device() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformAppleSimulator::~PlatformAppleSimulator() {} - -lldb_private::Status PlatformAppleSimulator::LaunchProcess( - lldb_private::ProcessLaunchInfo &launch_info) { -#if defined(__APPLE__) - LoadCoreSimulator(); - CoreSimulatorSupport::Device device(GetSimulatorDevice()); - - if (device.GetState() != CoreSimulatorSupport::Device::State::Booted) { - Status boot_err; - device.Boot(boot_err); - if (boot_err.Fail()) - return boot_err; - } - - auto spawned = device.Spawn(launch_info); - - if (spawned) { - launch_info.SetProcessID(spawned.GetPID()); - return Status(); - } else - return spawned.GetError(); -#else - Status err; - err.SetErrorString(UNSUPPORTED_ERROR); - return err; -#endif -} - -void PlatformAppleSimulator::GetStatus(Stream &strm) { -#if defined(__APPLE__) - // This will get called by subclasses, so just output status on the current - // simulator - PlatformAppleSimulator::LoadCoreSimulator(); - - CoreSimulatorSupport::DeviceSet devices = - CoreSimulatorSupport::DeviceSet::GetAvailableDevices( - GetDeveloperDirectory()); - const size_t num_devices = devices.GetNumDevices(); - if (num_devices) { - strm.Printf("Available devices:\n"); - for (size_t i = 0; i < num_devices; ++i) { - CoreSimulatorSupport::Device device = devices.GetDeviceAtIndex(i); - strm.Printf(" %s: %s\n", device.GetUDID().c_str(), - device.GetName().c_str()); - } - - if (m_device.hasValue() && m_device->operator bool()) { - strm.Printf("Current device: %s: %s", m_device->GetUDID().c_str(), - m_device->GetName().c_str()); - if (m_device->GetState() == CoreSimulatorSupport::Device::State::Booted) { - strm.Printf(" state = booted"); - } - strm.Printf("\nType \"platform connect <ARG>\" where <ARG> is a device " - "UDID or a device name to disconnect and connect to a " - "different device.\n"); - - } else { - strm.Printf("No current device is selected, \"platform connect <ARG>\" " - "where <ARG> is a device UDID or a device name to connect to " - "a specific device.\n"); - } - - } else { - strm.Printf("No devices are available.\n"); - } -#else - strm.Printf(UNSUPPORTED_ERROR); -#endif -} - -Status PlatformAppleSimulator::ConnectRemote(Args &args) { -#if defined(__APPLE__) - Status error; - if (args.GetArgumentCount() == 1) { - if (m_device) - DisconnectRemote(); - PlatformAppleSimulator::LoadCoreSimulator(); - const char *arg_cstr = args.GetArgumentAtIndex(0); - if (arg_cstr) { - std::string arg_str(arg_cstr); - CoreSimulatorSupport::DeviceSet devices = - CoreSimulatorSupport::DeviceSet::GetAvailableDevices( - GetDeveloperDirectory()); - devices.ForEach( - [this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool { - if (arg_str == device.GetUDID() || arg_str == device.GetName()) { - m_device = device; - return false; // Stop iterating - } else { - return true; // Keep iterating - } - }); - if (!m_device) - error.SetErrorStringWithFormat( - "no device with UDID or name '%s' was found", arg_cstr); - } - } else { - error.SetErrorString("this command take a single UDID argument of the " - "device you want to connect to."); - } - return error; -#else - Status err; - err.SetErrorString(UNSUPPORTED_ERROR); - return err; -#endif -} - -Status PlatformAppleSimulator::DisconnectRemote() { -#if defined(__APPLE__) - m_device.reset(); - return Status(); -#else - Status err; - err.SetErrorString(UNSUPPORTED_ERROR); - return err; -#endif -} - -lldb::ProcessSP PlatformAppleSimulator::DebugProcess( - ProcessLaunchInfo &launch_info, Debugger &debugger, - Target *target, // Can be NULL, if NULL create a new target, else use - // existing one - Status &error) { -#if defined(__APPLE__) - ProcessSP process_sp; - // Make sure we stop at the entry point - launch_info.GetFlags().Set(eLaunchFlagDebug); - // We always launch the process we are going to debug in a separate process - // group, since then we can handle ^C interrupts ourselves w/o having to - // worry about the target getting them as well. - launch_info.SetLaunchInSeparateProcessGroup(true); - - error = LaunchProcess(launch_info); - if (error.Success()) { - if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - ProcessAttachInfo attach_info(launch_info); - process_sp = Attach(attach_info, debugger, target, error); - if (process_sp) { - launch_info.SetHijackListener(attach_info.GetHijackListener()); - - // Since we attached to the process, it will think it needs to detach - // if the process object just goes away without an explicit call to - // Process::Kill() or Process::Detach(), so let it know to kill the - // process if this happens. - process_sp->SetShouldDetach(false); - - // If we didn't have any file actions, the pseudo terminal might have - // been used where the slave side was given as the file to open for - // stdin/out/err after we have already opened the master so we can - // read/write stdin/out/err. - int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); - if (pty_fd != PseudoTerminal::invalid_fd) { - process_sp->SetSTDIOFileDescriptor(pty_fd); - } - } - } - } - - return process_sp; -#else - return ProcessSP(); -#endif -} - -FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() { -#if defined(__APPLE__) - std::lock_guard<std::mutex> guard(m_core_sim_path_mutex); - if (!m_core_simulator_framework_path.hasValue()) { - const char *developer_dir = GetDeveloperDirectory(); - if (developer_dir) { - StreamString cs_path; - cs_path.Printf( - "%s/Library/PrivateFrameworks/CoreSimulator.framework/CoreSimulator", - developer_dir); - m_core_simulator_framework_path = FileSpec(cs_path.GetData()); - FileSystem::Instance().Resolve(*m_core_simulator_framework_path); - } - } - - return m_core_simulator_framework_path.getValue(); -#else - return FileSpec(); -#endif -} - -void PlatformAppleSimulator::LoadCoreSimulator() { -#if defined(__APPLE__) - static llvm::once_flag g_load_core_sim_flag; - llvm::call_once(g_load_core_sim_flag, [this] { - const std::string core_sim_path(GetCoreSimulatorPath().GetPath()); - if (core_sim_path.size()) - dlopen(core_sim_path.c_str(), RTLD_LAZY); - }); -#endif -} - -#if defined(__APPLE__) -CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() { - if (!m_device.hasValue()) { - const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id = - CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone; - m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices( - GetDeveloperDirectory()) - .GetFanciest(dev_id); - } - - if (m_device.hasValue()) - return m_device.getValue(); - else - return CoreSimulatorSupport::Device(); -} -#endif diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h deleted file mode 100644 index daae376cc00b5..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h +++ /dev/null @@ -1,68 +0,0 @@ -//===-- PlatformAppleSimulator.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformAppleSimulator_h_ -#define liblldb_PlatformAppleSimulator_h_ - -#include <mutex> - -#include "Plugins/Platform/MacOSX/PlatformDarwin.h" -#include "Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h" -#include "lldb/Utility/FileSpec.h" - -#include "llvm/ADT/Optional.h" - -class PlatformAppleSimulator : public PlatformDarwin { -public: - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - //------------------------------------------------------------ - // Class Methods - //------------------------------------------------------------ - PlatformAppleSimulator(); - - virtual ~PlatformAppleSimulator(); - - lldb_private::Status - LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - - void GetStatus(lldb_private::Stream &strm) override; - - lldb_private::Status ConnectRemote(lldb_private::Args &args) override; - - lldb_private::Status DisconnectRemote() override; - - lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Status &error) override; - -protected: - std::mutex m_core_sim_path_mutex; - llvm::Optional<lldb_private::FileSpec> m_core_simulator_framework_path; - llvm::Optional<CoreSimulatorSupport::Device> m_device; - - lldb_private::FileSpec GetCoreSimulatorPath(); - - void LoadCoreSimulator(); - -#if defined(__APPLE__) - CoreSimulatorSupport::Device GetSimulatorDevice(); -#endif - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformAppleSimulator); -}; - -#endif // liblldb_PlatformAppleSimulator_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp deleted file mode 100644 index 62bd3c3ed1f81..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp +++ /dev/null @@ -1,393 +0,0 @@ -//===-- PlatformAppleTVSimulator.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformAppleTVSimulator.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -#include "llvm/Support/FileSystem.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformAppleTVSimulator::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin( - PlatformAppleTVSimulator::GetPluginNameStatic(), - PlatformAppleTVSimulator::GetDescriptionStatic(), - PlatformAppleTVSimulator::CreateInstance); - } -} - -void PlatformAppleTVSimulator::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformAppleTVSimulator::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformAppleTVSimulator::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::x86_64: { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; -#endif - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::TvOS: - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - if (create) { - if (log) - log->Printf("PlatformAppleTVSimulator::%s() creating platform", - __FUNCTION__); - - return PlatformSP(new PlatformAppleTVSimulator()); - } - - if (log) - log->Printf("PlatformAppleTVSimulator::%s() aborting creation of platform", - __FUNCTION__); - - return PlatformSP(); -} - -lldb_private::ConstString PlatformAppleTVSimulator::GetPluginNameStatic() { - static ConstString g_name("tvos-simulator"); - return g_name; -} - -const char *PlatformAppleTVSimulator::GetDescriptionStatic() { - return "Apple TV simulator platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformAppleTVSimulator::PlatformAppleTVSimulator() - : PlatformDarwin(true), m_sdk_dir_mutex(), m_sdk_directory() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformAppleTVSimulator::~PlatformAppleTVSimulator() {} - -void PlatformAppleTVSimulator::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - const char *sdk_directory = GetSDKDirectoryAsCString(); - if (sdk_directory) - strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); - else - strm.PutCString(" SDK Path: error: unable to locate SDK\n"); -} - -Status PlatformAppleTVSimulator::ResolveExecutable( - const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Status error; - // Nothing special to do here, just use the actual file and architecture - - ModuleSpec resolved_module_spec(module_spec); - - // If we have "ls" as the exe_file, resolve the executable loation based on - // the current path variables - // TODO: resolve bare executables in the Platform SDK - // if (!resolved_exe_file.Exists()) - // resolved_exe_file.ResolveExecutableLocation (); - - // Resolve any executable within a bundle on MacOSX - // TODO: verify that this handles shallow bundles, if not then implement one - // ourselves - Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); - - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { - if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - - if (exe_module_sp && exe_module_sp->GetObjectFile()) - return error; - exe_module_sp.reset(); - } - // No valid architecture was specified or the exact ARM slice wasn't found - // so ask the platform for the architectures that we should be using (in - // the correct order) and see if we can find a match that way - StreamString arch_names; - ArchSpec platform_arch; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - // Only match x86 with x86 and x86_64 with x86_64... - if (!module_spec.GetArchitecture().IsValid() || - module_spec.GetArchitecture().GetCore() == - resolved_module_spec.GetArchitecture().GetCore()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString(platform_arch.GetArchitectureName()); - } - } - - if (error.Fail() || !exe_module_sp) { - if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetString().str().c_str()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } else { - error.SetErrorStringWithFormat("'%s' does not exist", - module_spec.GetFileSpec().GetPath().c_str()); - } - - return error; -} - -static FileSystem::EnumerateDirectoryResult -EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft, - llvm::StringRef path) { - if (ft == llvm::sys::fs::file_type::directory_file) { - FileSpec file_spec(path); - const char *filename = file_spec.GetFilename().GetCString(); - if (filename && - strncmp(filename, "AppleTVSimulator", strlen("AppleTVSimulator")) == - 0) { - ::snprintf((char *)baton, PATH_MAX, "%s", filename); - return FileSystem::eEnumerateDirectoryResultQuit; - } - } - return FileSystem::eEnumerateDirectoryResultNext; -} - -const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() { - std::lock_guard<std::mutex> guard(m_sdk_dir_mutex); - if (m_sdk_directory.empty()) { - const char *developer_dir = GetDeveloperDirectory(); - if (developer_dir) { - char sdks_directory[PATH_MAX]; - char sdk_dirname[PATH_MAX]; - sdk_dirname[0] = '\0'; - snprintf(sdks_directory, sizeof(sdks_directory), - "%s/Platforms/AppleTVSimulator.platform/Developer/SDKs", - developer_dir); - FileSpec simulator_sdk_spec; - bool find_directories = true; - bool find_files = false; - bool find_other = false; - FileSystem::Instance().EnumerateDirectory( - sdks_directory, find_directories, find_files, find_other, - EnumerateDirectoryCallback, sdk_dirname); - - if (sdk_dirname[0]) { - m_sdk_directory = sdks_directory; - m_sdk_directory.append(1, '/'); - m_sdk_directory.append(sdk_dirname); - return m_sdk_directory.c_str(); - } - } - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_sdk_directory.assign(1, '\0'); - } - - // We should have put a single NULL character into m_sdk_directory or it - // should have a valid path if the code gets here - assert(m_sdk_directory.empty() == false); - if (m_sdk_directory[0]) - return m_sdk_directory.c_str(); - return NULL; -} - -Status PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - Status error; - char platform_file_path[PATH_MAX]; - if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { - char resolved_path[PATH_MAX]; - - const char *sdk_dir = GetSDKDirectoryAsCString(); - if (sdk_dir) { - ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir, - platform_file_path); - - // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - - // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - } - error.SetErrorStringWithFormat( - "unable to locate a platform file for '%s' in platform '%s'", - platform_file_path, GetPluginName().GetCString()); - } else { - error.SetErrorString("invalid platform file argument"); - } - return error; -} - -Status PlatformAppleTVSimulator::GetSharedModule( - const ModuleSpec &module_spec, lldb_private::Process *process, - ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, - ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For AppleTV, the SDK files are all cached locally on the host system. So - // first we ask for the file in the cached SDK, then we attempt to get a - // shared module for the right architecture with the right UUID. - Status error; - ModuleSpec platform_module_spec(module_spec); - const FileSpec &platform_file = module_spec.GetFileSpec(); - error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(), - platform_module_spec.GetFileSpec()); - if (error.Success()) { - error = ResolveExecutable(platform_module_spec, module_sp, - module_search_paths_ptr); - } else { - const bool always_create = false; - error = ModuleList::GetSharedModule( - module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr, always_create); - } - if (module_sp) - module_sp->SetPlatformFileSpec(platform_file); - - return error; -} - -uint32_t PlatformAppleTVSimulator::FindProcesses( - const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) { - ProcessInstanceInfoList all_osx_process_infos; - // First we get all OSX processes - const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos); - - // Now we filter them down to only the TvOS triples - for (uint32_t i = 0; i < n; ++i) { - const ProcessInstanceInfo &proc_info = - all_osx_process_infos.GetProcessInfoAtIndex(i); - if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::TvOS) { - process_infos.Append(proc_info); - } - } - return process_infos.GetSize(); -} - -bool PlatformAppleTVSimulator::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - static const ArchSpec platform_arch( - HostInfo::GetArchitecture(HostInfo::eArchKind64)); - - if (idx == 0) { - arch = platform_arch; - if (arch.IsValid()) { - arch.GetTriple().setOS(llvm::Triple::TvOS); - return true; - } - } - return false; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h deleted file mode 100644 index 9a4da589c7ead..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- PlatformAppleTVSimulator.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformAppleTVSimulator_h_ -#define liblldb_PlatformAppleTVSimulator_h_ - -#include "PlatformDarwin.h" - -class PlatformAppleTVSimulator : public PlatformDarwin { -public: - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // Class Methods - //------------------------------------------------------------ - PlatformAppleTVSimulator(); - - virtual ~PlatformAppleTVSimulator(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - lldb_private::Status ResolveExecutable( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr) override; - - const char *GetDescription() override { return GetDescriptionStatic(); } - - void GetStatus(lldb_private::Stream &strm) override; - - virtual lldb_private::Status - GetSymbolFile(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file); - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - uint32_t - FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, - lldb_private::ProcessInstanceInfoList &process_infos) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - void - AddClangModuleCompilationOptions(lldb_private::Target *target, - std::vector<std::string> &options) override { - return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); - } - -protected: - std::mutex m_sdk_dir_mutex; - std::string m_sdk_directory; - std::string m_build_update; - - const char *GetSDKDirectoryAsCString(); - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformAppleTVSimulator); -}; - -#endif // liblldb_PlatformAppleTVSimulator_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp deleted file mode 100644 index ec112cc0b9c52..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp +++ /dev/null @@ -1,394 +0,0 @@ -//===-- PlatformAppleWatchSimulator.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformAppleWatchSimulator.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformAppleWatchSimulator::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin( - PlatformAppleWatchSimulator::GetPluginNameStatic(), - PlatformAppleWatchSimulator::GetDescriptionStatic(), - PlatformAppleWatchSimulator::CreateInstance); - } -} - -void PlatformAppleWatchSimulator::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin( - PlatformAppleWatchSimulator::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformAppleWatchSimulator::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::x86_64: { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; -#endif - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::WatchOS: - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - if (create) { - if (log) - log->Printf("PlatformAppleWatchSimulator::%s() creating platform", - __FUNCTION__); - - return PlatformSP(new PlatformAppleWatchSimulator()); - } - - if (log) - log->Printf( - "PlatformAppleWatchSimulator::%s() aborting creation of platform", - __FUNCTION__); - - return PlatformSP(); -} - -lldb_private::ConstString PlatformAppleWatchSimulator::GetPluginNameStatic() { - static ConstString g_name("watchos-simulator"); - return g_name; -} - -const char *PlatformAppleWatchSimulator::GetDescriptionStatic() { - return "Apple Watch simulator platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformAppleWatchSimulator::PlatformAppleWatchSimulator() - : PlatformDarwin(true), m_sdk_directory() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformAppleWatchSimulator::~PlatformAppleWatchSimulator() {} - -void PlatformAppleWatchSimulator::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - const char *sdk_directory = GetSDKDirectoryAsCString(); - if (sdk_directory) - strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); - else - strm.PutCString(" SDK Path: error: unable to locate SDK\n"); -} - -Status PlatformAppleWatchSimulator::ResolveExecutable( - const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Status error; - // Nothing special to do here, just use the actual file and architecture - - ModuleSpec resolved_module_spec(module_spec); - - // If we have "ls" as the exe_file, resolve the executable loation based on - // the current path variables - // TODO: resolve bare executables in the Platform SDK - // if (!resolved_exe_file.Exists()) - // resolved_exe_file.ResolveExecutableLocation (); - - // Resolve any executable within a bundle on MacOSX - // TODO: verify that this handles shallow bundles, if not then implement one - // ourselves - Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); - - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { - if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - - if (exe_module_sp && exe_module_sp->GetObjectFile()) - return error; - exe_module_sp.reset(); - } - // No valid architecture was specified or the exact ARM slice wasn't found - // so ask the platform for the architectures that we should be using (in - // the correct order) and see if we can find a match that way - StreamString arch_names; - ArchSpec platform_arch; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - // Only match x86 with x86 and x86_64 with x86_64... - if (!module_spec.GetArchitecture().IsValid() || - module_spec.GetArchitecture().GetCore() == - resolved_module_spec.GetArchitecture().GetCore()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString(platform_arch.GetArchitectureName()); - } - } - - if (error.Fail() || !exe_module_sp) { - if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetString().str().c_str()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } else { - error.SetErrorStringWithFormat("'%s' does not exist", - module_spec.GetFileSpec().GetPath().c_str()); - } - - return error; -} - -static FileSystem::EnumerateDirectoryResult -EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft, - llvm::StringRef path) { - if (ft == llvm::sys::fs::file_type::directory_file) { - FileSpec file_spec(path); - const char *filename = file_spec.GetFilename().GetCString(); - if (filename && - strncmp(filename, "AppleWatchSimulator", - strlen("AppleWatchSimulator")) == 0) { - ::snprintf((char *)baton, PATH_MAX, "%s", filename); - return FileSystem::eEnumerateDirectoryResultQuit; - } - } - return FileSystem::eEnumerateDirectoryResultNext; -} - -const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() { - std::lock_guard<std::mutex> guard(m_sdk_dir_mutex); - if (m_sdk_directory.empty()) { - const char *developer_dir = GetDeveloperDirectory(); - if (developer_dir) { - char sdks_directory[PATH_MAX]; - char sdk_dirname[PATH_MAX]; - sdk_dirname[0] = '\0'; - snprintf(sdks_directory, sizeof(sdks_directory), - "%s/Platforms/AppleWatchSimulator.platform/Developer/SDKs", - developer_dir); - FileSpec simulator_sdk_spec; - bool find_directories = true; - bool find_files = false; - bool find_other = false; - FileSystem::Instance().EnumerateDirectory( - sdks_directory, find_directories, find_files, find_other, - EnumerateDirectoryCallback, sdk_dirname); - - if (sdk_dirname[0]) { - m_sdk_directory = sdks_directory; - m_sdk_directory.append(1, '/'); - m_sdk_directory.append(sdk_dirname); - return m_sdk_directory.c_str(); - } - } - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_sdk_directory.assign(1, '\0'); - } - - // We should have put a single NULL character into m_sdk_directory or it - // should have a valid path if the code gets here - assert(m_sdk_directory.empty() == false); - if (m_sdk_directory[0]) - return m_sdk_directory.c_str(); - return NULL; -} - -Status PlatformAppleWatchSimulator::GetSymbolFile(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - Status error; - char platform_file_path[PATH_MAX]; - if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { - char resolved_path[PATH_MAX]; - - const char *sdk_dir = GetSDKDirectoryAsCString(); - if (sdk_dir) { - ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir, - platform_file_path); - - // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - - // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - } - error.SetErrorStringWithFormat( - "unable to locate a platform file for '%s' in platform '%s'", - platform_file_path, GetPluginName().GetCString()); - } else { - error.SetErrorString("invalid platform file argument"); - } - return error; -} - -Status PlatformAppleWatchSimulator::GetSharedModule( - const ModuleSpec &module_spec, lldb_private::Process *process, - ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, - ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - // For AppleWatch, the SDK files are all cached locally on the host system. - // So first we ask for the file in the cached SDK, then we attempt to get a - // shared module for the right architecture with the right UUID. - Status error; - ModuleSpec platform_module_spec(module_spec); - const FileSpec &platform_file = module_spec.GetFileSpec(); - error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(), - platform_module_spec.GetFileSpec()); - if (error.Success()) { - error = ResolveExecutable(platform_module_spec, module_sp, - module_search_paths_ptr); - } else { - const bool always_create = false; - error = ModuleList::GetSharedModule( - module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr, always_create); - } - if (module_sp) - module_sp->SetPlatformFileSpec(platform_file); - - return error; -} - -uint32_t PlatformAppleWatchSimulator::FindProcesses( - const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) { - ProcessInstanceInfoList all_osx_process_infos; - // First we get all OSX processes - const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos); - - // Now we filter them down to only the WatchOS triples - for (uint32_t i = 0; i < n; ++i) { - const ProcessInstanceInfo &proc_info = - all_osx_process_infos.GetProcessInfoAtIndex(i); - if (proc_info.GetArchitecture().GetTriple().getOS() == - llvm::Triple::WatchOS) { - process_infos.Append(proc_info); - } - } - return process_infos.GetSize(); -} - -bool PlatformAppleWatchSimulator::GetSupportedArchitectureAtIndex( - uint32_t idx, ArchSpec &arch) { - static const ArchSpec platform_arch( - HostInfo::GetArchitecture(HostInfo::eArchKind64)); - - if (idx == 0) { - arch = platform_arch; - if (arch.IsValid()) { - arch.GetTriple().setOS(llvm::Triple::WatchOS); - return true; - } - } - return false; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h deleted file mode 100644 index c240a09e3afd1..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- PlatformAppleWatchSimulator.h ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformAppleWatchSimulator_h_ -#define liblldb_PlatformAppleWatchSimulator_h_ - -#include "PlatformDarwin.h" - -class PlatformAppleWatchSimulator : public PlatformDarwin { -public: - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // Class Methods - //------------------------------------------------------------ - PlatformAppleWatchSimulator(); - - virtual ~PlatformAppleWatchSimulator(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - lldb_private::Status ResolveExecutable( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr) override; - - const char *GetDescription() override { return GetDescriptionStatic(); } - - void GetStatus(lldb_private::Stream &strm) override; - - virtual lldb_private::Status - GetSymbolFile(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file); - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - uint32_t - FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, - lldb_private::ProcessInstanceInfoList &process_infos) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - void - AddClangModuleCompilationOptions(lldb_private::Target *target, - std::vector<std::string> &options) override { - return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); - } - -protected: - std::mutex m_sdk_dir_mutex; - std::string m_sdk_directory; - std::string m_build_update; - - const char *GetSDKDirectoryAsCString(); - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformAppleWatchSimulator); -}; - -#endif // liblldb_PlatformAppleWatchSimulator_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp deleted file mode 100644 index 3868d97700e07..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ /dev/null @@ -1,1757 +0,0 @@ -//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformDarwin.h" - -#include <string.h> - -#include <algorithm> -#include <mutex> - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/BreakpointSite.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/Symbols.h" -#include "lldb/Host/XML.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/Timer.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/VersionTuple.h" - -#if defined(__APPLE__) -#include <TargetConditionals.h> -#endif - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformDarwin::PlatformDarwin(bool is_host) - : PlatformPOSIX(is_host), // This is the local host platform - m_developer_directory() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformDarwin::~PlatformDarwin() {} - -FileSpecList PlatformDarwin::LocateExecutableScriptingResources( - Target *target, Module &module, Stream *feedback_stream) { - FileSpecList file_list; - if (target && - target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython) { - // NB some extensions might be meaningful and should not be stripped - - // "this.binary.file" - // should not lose ".file" but GetFileNameStrippingExtension() will do - // precisely that. Ideally, we should have a per-platform list of - // extensions (".exe", ".app", ".dSYM", ".framework") which should be - // stripped while leaving "this.binary.file" as-is. - ScriptInterpreter *script_interpreter = - target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - - FileSpec module_spec = module.GetFileSpec(); - - if (module_spec) { - SymbolVendor *symbols = module.GetSymbolVendor(); - if (symbols) { - SymbolFile *symfile = symbols->GetSymbolFile(); - if (symfile) { - ObjectFile *objfile = symfile->GetObjectFile(); - if (objfile) { - FileSpec symfile_spec(objfile->GetFileSpec()); - if (symfile_spec && FileSystem::Instance().Exists(symfile_spec)) { - while (module_spec.GetFilename()) { - std::string module_basename( - module_spec.GetFilename().GetCString()); - std::string original_module_basename(module_basename); - - bool was_keyword = false; - - // FIXME: for Python, we cannot allow certain characters in - // module - // filenames we import. Theoretically, different scripting - // languages may have different sets of forbidden tokens in - // filenames, and that should be dealt with by each - // ScriptInterpreter. For now, we just replace dots with - // underscores, but if we ever support anything other than - // Python we will need to rework this - std::replace(module_basename.begin(), module_basename.end(), - '.', '_'); - std::replace(module_basename.begin(), module_basename.end(), - ' ', '_'); - std::replace(module_basename.begin(), module_basename.end(), - '-', '_'); - if (script_interpreter && - script_interpreter->IsReservedWord( - module_basename.c_str())) { - module_basename.insert(module_basename.begin(), '_'); - was_keyword = true; - } - - StreamString path_string; - StreamString original_path_string; - // for OSX we are going to be in - // .dSYM/Contents/Resources/DWARF/<basename> let us go to - // .dSYM/Contents/Resources/Python/<basename>.py and see if the - // file exists - path_string.Printf("%s/../Python/%s.py", - symfile_spec.GetDirectory().GetCString(), - module_basename.c_str()); - original_path_string.Printf( - "%s/../Python/%s.py", - symfile_spec.GetDirectory().GetCString(), - original_module_basename.c_str()); - FileSpec script_fspec(path_string.GetString()); - FileSystem::Instance().Resolve(script_fspec); - FileSpec orig_script_fspec(original_path_string.GetString()); - FileSystem::Instance().Resolve(orig_script_fspec); - - // if we did some replacements of reserved characters, and a - // file with the untampered name exists, then warn the user - // that the file as-is shall not be loaded - if (feedback_stream) { - if (module_basename != original_module_basename && - FileSystem::Instance().Exists(orig_script_fspec)) { - const char *reason_for_complaint = - was_keyword ? "conflicts with a keyword" - : "contains reserved characters"; - if (FileSystem::Instance().Exists(script_fspec)) - feedback_stream->Printf( - "warning: the symbol file '%s' contains a debug " - "script. However, its name" - " '%s' %s and as such cannot be loaded. LLDB will" - " load '%s' instead. Consider removing the file with " - "the malformed name to" - " eliminate this warning.\n", - symfile_spec.GetPath().c_str(), - original_path_string.GetData(), reason_for_complaint, - path_string.GetData()); - else - feedback_stream->Printf( - "warning: the symbol file '%s' contains a debug " - "script. However, its name" - " %s and as such cannot be loaded. If you intend" - " to have this script loaded, please rename '%s' to " - "'%s' and retry.\n", - symfile_spec.GetPath().c_str(), reason_for_complaint, - original_path_string.GetData(), - path_string.GetData()); - } - } - - if (FileSystem::Instance().Exists(script_fspec)) { - file_list.Append(script_fspec); - break; - } - - // If we didn't find the python file, then keep stripping the - // extensions and try again - ConstString filename_no_extension( - module_spec.GetFileNameStrippingExtension()); - if (module_spec.GetFilename() == filename_no_extension) - break; - - module_spec.GetFilename() = filename_no_extension; - } - } - } - } - } - } - } - return file_list; -} - -Status PlatformDarwin::ResolveSymbolFile(Target &target, - const ModuleSpec &sym_spec, - FileSpec &sym_file) { - sym_file = sym_spec.GetSymbolFileSpec(); - if (FileSystem::Instance().IsDirectory(sym_file)) { - sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(), - sym_spec.GetArchitecturePtr()); - } - return {}; -} - -static lldb_private::Status -MakeCacheFolderForFile(const FileSpec &module_cache_spec) { - FileSpec module_cache_folder = - module_cache_spec.CopyByRemovingLastPathComponent(); - return llvm::sys::fs::create_directory(module_cache_folder.GetPath()); -} - -static lldb_private::Status -BringInRemoteFile(Platform *platform, - const lldb_private::ModuleSpec &module_spec, - const FileSpec &module_cache_spec) { - MakeCacheFolderForFile(module_cache_spec); - Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec); - return err; -} - -lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("[%s] Trying to find module %s/%s - platform path %s/%s symbol " - "path %s/%s", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString(), - module_spec.GetPlatformFileSpec().GetDirectory().AsCString(), - module_spec.GetPlatformFileSpec().GetFilename().AsCString(), - module_spec.GetSymbolFileSpec().GetDirectory().AsCString(), - module_spec.GetSymbolFileSpec().GetFilename().AsCString()); - - Status err; - - err = ModuleList::GetSharedModule(module_spec, module_sp, - module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr); - if (module_sp) - return err; - - if (!IsHost()) { - std::string cache_path(GetLocalCacheDirectory()); - // Only search for a locally cached file if we have a valid cache path - if (!cache_path.empty()) { - std::string module_path(module_spec.GetFileSpec().GetPath()); - cache_path.append(module_path); - FileSpec module_cache_spec(cache_path); - - // if rsync is supported, always bring in the file - rsync will be very - // efficient when files are the same on the local and remote end of the - // connection - if (this->GetSupportsRSync()) { - err = BringInRemoteFile(this, module_spec, module_cache_spec); - if (err.Fail()) - return err; - if (FileSystem::Instance().Exists(module_cache_spec)) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("[%s] module %s/%s was rsynced and is now there", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString()); - ModuleSpec local_spec(module_cache_spec, - module_spec.GetArchitecture()); - module_sp.reset(new Module(local_spec)); - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - return Status(); - } - } - - // try to find the module in the cache - if (FileSystem::Instance().Exists(module_cache_spec)) { - // get the local and remote MD5 and compare - if (m_remote_platform_sp) { - // when going over the *slow* GDB remote transfer mechanism we first - // check the hashes of the files - and only do the actual transfer if - // they differ - uint64_t high_local, high_remote, low_local, low_remote; - auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath()); - if (!MD5) - return Status(MD5.getError()); - std::tie(high_local, low_local) = MD5->words(); - - m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), - low_remote, high_remote); - if (low_local != low_remote || high_local != high_remote) { - // bring in the remote file - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf( - "[%s] module %s/%s needs to be replaced from remote copy", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString()); - Status err = - BringInRemoteFile(this, module_spec, module_cache_spec); - if (err.Fail()) - return err; - } - } - - ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); - module_sp.reset(new Module(local_spec)); - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("[%s] module %s/%s was found in the cache", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString()); - return Status(); - } - - // bring in the remote module file - if (log) - log->Printf("[%s] module %s/%s needs to come in remotely", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString()); - Status err = BringInRemoteFile(this, module_spec, module_cache_spec); - if (err.Fail()) - return err; - if (FileSystem::Instance().Exists(module_cache_spec)) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("[%s] module %s/%s is now cached and fine", - (IsHost() ? "host" : "remote"), - module_spec.GetFileSpec().GetDirectory().AsCString(), - module_spec.GetFileSpec().GetFilename().AsCString()); - ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture()); - module_sp.reset(new Module(local_spec)); - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - return Status(); - } else - return Status("unable to obtain valid module file"); - } else - return Status("no cache path"); - } else - return Status("unable to resolve module"); -} - -Status PlatformDarwin::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - Status error; - module_sp.reset(); - - if (IsRemote()) { - // If we have a remote platform always, let it try and locate the shared - // module first. - if (m_remote_platform_sp) { - error = m_remote_platform_sp->GetSharedModule( - module_spec, process, module_sp, module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - } - } - - if (!module_sp) { - // Fall back to the local platform and find the file locally - error = Platform::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - - const FileSpec &platform_file = module_spec.GetFileSpec(); - if (!module_sp && module_search_paths_ptr && platform_file) { - // We can try to pull off part of the file path up to the bundle - // directory level and try any module search paths... - FileSpec bundle_directory; - if (Host::GetBundleDirectory(platform_file, bundle_directory)) { - if (platform_file == bundle_directory) { - ModuleSpec new_module_spec(module_spec); - new_module_spec.GetFileSpec() = bundle_directory; - if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) { - Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, old_module_sp_ptr, - did_create_ptr)); - - if (module_sp) - return new_error; - } - } else { - char platform_path[PATH_MAX]; - char bundle_dir[PATH_MAX]; - platform_file.GetPath(platform_path, sizeof(platform_path)); - const size_t bundle_directory_len = - bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir)); - char new_path[PATH_MAX]; - size_t num_module_search_paths = module_search_paths_ptr->GetSize(); - for (size_t i = 0; i < num_module_search_paths; ++i) { - const size_t search_path_len = - module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath( - new_path, sizeof(new_path)); - if (search_path_len < sizeof(new_path)) { - snprintf(new_path + search_path_len, - sizeof(new_path) - search_path_len, "/%s", - platform_path + bundle_directory_len); - FileSpec new_file_spec(new_path); - if (FileSystem::Instance().Exists(new_file_spec)) { - ModuleSpec new_module_spec(module_spec); - new_module_spec.GetFileSpec() = new_file_spec; - Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, - old_module_sp_ptr, did_create_ptr)); - - if (module_sp) { - module_sp->SetPlatformFileSpec(new_file_spec); - return new_error; - } - } - } - } - } - } - } - } - if (module_sp) - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - return error; -} - -size_t -PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target, - BreakpointSite *bp_site) { - const uint8_t *trap_opcode = nullptr; - uint32_t trap_opcode_size = 0; - bool bp_is_thumb = false; - - llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); - switch (machine) { - case llvm::Triple::aarch64: { - // TODO: fix this with actual darwin breakpoint opcode for arm64. - // right now debugging uses the Z packets with GDB remote so this is not - // needed, but the size needs to be correct... - static const uint8_t g_arm64_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; - trap_opcode = g_arm64_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm64_breakpoint_opcode); - } break; - - case llvm::Triple::thumb: - bp_is_thumb = true; - LLVM_FALLTHROUGH; - case llvm::Triple::arm: { - static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; - static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE}; - - // Auto detect arm/thumb if it wasn't explicitly specified - if (!bp_is_thumb) { - lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); - if (bp_loc_sp) - bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() == - AddressClass::eCodeAlternateISA; - } - if (bp_is_thumb) { - trap_opcode = g_thumb_breakpooint_opcode; - trap_opcode_size = sizeof(g_thumb_breakpooint_opcode); - break; - } - trap_opcode = g_arm_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm_breakpoint_opcode); - } break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: { - static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08}; - trap_opcode = g_ppc_breakpoint_opcode; - trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); - } break; - - default: - return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); - } - - if (trap_opcode && trap_opcode_size) { - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - } - return 0; -} - -bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches( - lldb_private::Target &target, const lldb::ModuleSP &module_sp) { - if (!module_sp) - return false; - - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (!obj_file) - return false; - - ObjectFile::Type obj_type = obj_file->GetType(); - return obj_type == ObjectFile::eTypeDynamicLinker; -} - -bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) { - switch (idx) { - case 0: - arch = host_arch; - return true; - - case 1: - arch.SetTriple("x86_64-apple-macosx"); - return true; - - case 2: - arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); - return true; - - default: - return false; - } - } else { - if (idx == 0) { - arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - return arch.IsValid(); - } else if (idx == 1) { - ArchSpec platform_arch( - HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); - ArchSpec platform_arch64( - HostInfo::GetArchitecture(HostInfo::eArchKind64)); - if (platform_arch.IsExactMatch(platform_arch64)) { - // This macosx platform supports both 32 and 64 bit. Since we already - // returned the 64 bit arch for idx == 0, return the 32 bit arch for - // idx == 1 - arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); - return arch.IsValid(); - } - } - } - return false; -} - -// The architecture selection rules for arm processors These cpu subtypes have -// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f -// processor. - -bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - ArchSpec system_arch(GetSystemArchitecture()); - -// When lldb is running on a watch or tv, set the arch OS name appropriately. -#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1 -#define OSNAME "tvos" -#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1 -#define OSNAME "watchos" -#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1 -#define OSNAME "bridgeos" -#else -#define OSNAME "ios" -#endif - - const ArchSpec::Core system_core = system_arch.GetCore(); - switch (system_core) { - default: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv7f-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv7k-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv7s-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv7m-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("armv7em-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumbv7f-apple-" OSNAME); - return true; - case 14: - arch.SetTriple("thumbv7k-apple-" OSNAME); - return true; - case 15: - arch.SetTriple("thumbv7s-apple-" OSNAME); - return true; - case 16: - arch.SetTriple("thumbv7m-apple-" OSNAME); - return true; - case 17: - arch.SetTriple("thumbv7em-apple-" OSNAME); - return true; - case 18: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 19: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 20: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 21: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 22: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_arm64: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7s-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv7f-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv7m-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv7em-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv7f-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumbv7k-apple-" OSNAME); - return true; - case 14: - arch.SetTriple("thumbv7s-apple-" OSNAME); - return true; - case 15: - arch.SetTriple("thumbv7m-apple-" OSNAME); - return true; - case 16: - arch.SetTriple("thumbv7em-apple-" OSNAME); - return true; - case 17: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 18: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 19: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 20: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 21: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7f: - switch (idx) { - case 0: - arch.SetTriple("armv7f-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv7f-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7k: - switch (idx) { - case 0: - arch.SetTriple("armv7k-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv7k-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7s: - switch (idx) { - case 0: - arch.SetTriple("armv7s-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv7s-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7m: - switch (idx) { - case 0: - arch.SetTriple("armv7m-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv7m-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7em: - switch (idx) { - case 0: - arch.SetTriple("armv7em-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv7em-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 12: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 13: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7: - switch (idx) { - case 0: - arch.SetTriple("armv7-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("thumbv7-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 10: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 11: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv6m: - switch (idx) { - case 0: - arch.SetTriple("armv6m-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("thumbv6m-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 8: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 9: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv6: - switch (idx) { - case 0: - arch.SetTriple("armv6-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("thumbv6-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 6: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 7: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv5: - switch (idx) { - case 0: - arch.SetTriple("armv5-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("thumbv5-apple-" OSNAME); - return true; - case 4: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 5: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv4: - switch (idx) { - case 0: - arch.SetTriple("armv4-apple-" OSNAME); - return true; - case 1: - arch.SetTriple("arm-apple-" OSNAME); - return true; - case 2: - arch.SetTriple("thumbv4t-apple-" OSNAME); - return true; - case 3: - arch.SetTriple("thumb-apple-" OSNAME); - return true; - default: - break; - } - break; - } - arch.Clear(); - return false; -} - -// Return a directory path like /Applications/Xcode.app/Contents/Developer -const char *PlatformDarwin::GetDeveloperDirectory() { - std::lock_guard<std::mutex> guard(m_mutex); - if (m_developer_directory.empty()) { - bool developer_dir_path_valid = false; - char developer_dir_path[PATH_MAX]; - - // Get the lldb framework's file path, and if it exists, truncate some - // components to only the developer directory path. - FileSpec temp_file_spec = HostInfo::GetShlibDir(); - if (temp_file_spec) { - if (temp_file_spec.GetPath(developer_dir_path, - sizeof(developer_dir_path))) { - // e.g. - // /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework - char *shared_frameworks = - strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework"); - if (shared_frameworks) { - shared_frameworks[0] = '\0'; // truncate developer_dir_path at this point - strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on - developer_dir_path_valid = true; - } else { - // e.g. - // /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework - char *developer_toolchains = - strstr(developer_dir_path, "/Contents/Developer/Toolchains/"); - if (developer_toolchains) { - developer_toolchains += sizeof ("/Contents/Developer") - 1; - developer_toolchains[0] = '\0'; // truncate developer_dir_path at this point - developer_dir_path_valid = true; - } - } - } - } - - if (!developer_dir_path_valid) { - std::string xcode_dir_path; - const char *xcode_select_prefix_dir = getenv("XCODE_SELECT_PREFIX_DIR"); - if (xcode_select_prefix_dir) - xcode_dir_path.append(xcode_select_prefix_dir); - xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path"); - temp_file_spec.SetFile(xcode_dir_path, FileSpec::Style::native); - auto dir_buffer = - FileSystem::Instance().CreateDataBuffer(temp_file_spec.GetPath()); - if (dir_buffer && dir_buffer->GetByteSize() > 0) { - llvm::StringRef path_ref(dir_buffer->GetChars()); - // Trim tailing newlines and make sure there is enough room for a null - // terminator. - path_ref = - path_ref.rtrim("\r\n").take_front(sizeof(developer_dir_path) - 1); - ::memcpy(developer_dir_path, path_ref.data(), path_ref.size()); - developer_dir_path[path_ref.size()] = '\0'; - developer_dir_path_valid = true; - } - } - - if (!developer_dir_path_valid) { - FileSpec xcode_select_cmd("/usr/bin/xcode-select"); - if (FileSystem::Instance().Exists(xcode_select_cmd)) { - int exit_status = -1; - int signo = -1; - std::string command_output; - Status error = - Host::RunShellCommand("/usr/bin/xcode-select --print-path", - NULL, // current working directory - &exit_status, &signo, &command_output, - std::chrono::seconds(2), // short timeout - false); // don't run in a shell - if (error.Success() && exit_status == 0 && !command_output.empty()) { - const char *cmd_output_ptr = command_output.c_str(); - developer_dir_path[sizeof(developer_dir_path) - 1] = '\0'; - size_t i; - for (i = 0; i < sizeof(developer_dir_path) - 1; i++) { - if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || - cmd_output_ptr[i] == '\0') - break; - developer_dir_path[i] = cmd_output_ptr[i]; - } - developer_dir_path[i] = '\0'; - - FileSpec devel_dir(developer_dir_path); - if (FileSystem::Instance().IsDirectory(devel_dir)) { - developer_dir_path_valid = true; - } - } - } - } - - if (developer_dir_path_valid) { - temp_file_spec.SetFile(developer_dir_path, FileSpec::Style::native); - if (FileSystem::Instance().Exists(temp_file_spec)) { - m_developer_directory.assign(developer_dir_path); - return m_developer_directory.c_str(); - } - } - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_developer_directory.assign(1, '\0'); - } - - // We should have put a single NULL character into m_developer_directory or - // it should have a valid path if the code gets here - assert(m_developer_directory.empty() == false); - if (m_developer_directory[0]) - return m_developer_directory.c_str(); - return NULL; -} - -BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) { - BreakpointSP bp_sp; - static const char *g_bp_names[] = { - "start_wqthread", "_pthread_wqthread", "_pthread_start", - }; - - static const char *g_bp_modules[] = {"libsystem_c.dylib", - "libSystem.B.dylib"}; - - FileSpecList bp_modules; - for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) { - const char *bp_module = g_bp_modules[i]; - bp_modules.Append(FileSpec(bp_module)); - } - - bool internal = true; - bool hardware = false; - LazyBool skip_prologue = eLazyBoolNo; - bp_sp = target.CreateBreakpoint(&bp_modules, NULL, g_bp_names, - llvm::array_lengthof(g_bp_names), - eFunctionNameTypeFull, eLanguageTypeUnknown, - 0, skip_prologue, internal, hardware); - bp_sp->SetBreakpointKind("thread-creation"); - - return bp_sp; -} - -int32_t -PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { - const FileSpec &shell = launch_info.GetShell(); - if (!shell) - return 1; - - std::string shell_string = shell.GetPath(); - const char *shell_name = strrchr(shell_string.c_str(), '/'); - if (shell_name == NULL) - shell_name = shell_string.c_str(); - else - shell_name++; - - if (strcmp(shell_name, "sh") == 0) { - // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it - // only does this if the COMMAND_MODE environment variable is set to - // "legacy". - if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy") - return 2; - return 1; - } else if (strcmp(shell_name, "csh") == 0 || - strcmp(shell_name, "tcsh") == 0 || - strcmp(shell_name, "zsh") == 0) { - // csh and tcsh always seem to re-exec themselves. - return 2; - } else - return 1; -} - -void PlatformDarwin::CalculateTrapHandlerSymbolNames() { - m_trap_handlers.push_back(ConstString("_sigtramp")); -} - -static const char *const sdk_strings[] = { - "MacOSX", "iPhoneSimulator", "iPhoneOS", -}; - -static FileSpec CheckPathForXcode(const FileSpec &fspec) { - if (FileSystem::Instance().Exists(fspec)) { - const char substr[] = ".app/Contents"; - - std::string path_to_shlib = fspec.GetPath(); - size_t pos = path_to_shlib.rfind(substr); - if (pos != std::string::npos) { - path_to_shlib.erase(pos + strlen(substr)); - FileSpec ret(path_to_shlib); - - FileSpec xcode_binary_path = ret; - xcode_binary_path.AppendPathComponent("MacOS"); - xcode_binary_path.AppendPathComponent("Xcode"); - - if (FileSystem::Instance().Exists(xcode_binary_path)) { - return ret; - } - } - } - return FileSpec(); -} - -static FileSpec GetXcodeContentsPath() { - static FileSpec g_xcode_filespec; - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - - FileSpec fspec; - - // First get the program file spec. If lldb.so or LLDB.framework is running - // in a program and that program is Xcode, the path returned with be the - // path to Xcode.app/Contents/MacOS/Xcode, so this will be the correct - // Xcode to use. - fspec = HostInfo::GetProgramFileSpec(); - - if (fspec) { - // Ignore the current binary if it is python. - std::string basename_lower = fspec.GetFilename().GetCString(); - std::transform(basename_lower.begin(), basename_lower.end(), - basename_lower.begin(), tolower); - if (basename_lower != "python") { - g_xcode_filespec = CheckPathForXcode(fspec); - } - } - - // Next check DEVELOPER_DIR environment variable - if (!g_xcode_filespec) { - const char *developer_dir_env_var = getenv("DEVELOPER_DIR"); - if (developer_dir_env_var && developer_dir_env_var[0]) { - FileSpec developer_dir_spec = FileSpec(developer_dir_env_var); - FileSystem::Instance().Resolve(developer_dir_spec); - g_xcode_filespec = CheckPathForXcode(developer_dir_spec); - } - - // Fall back to using "xcrun" to find the selected Xcode - if (!g_xcode_filespec) { - int status = 0; - int signo = 0; - std::string output; - const char *command = "/usr/bin/xcode-select -p"; - lldb_private::Status error = Host::RunShellCommand( - command, // shell command to run - NULL, // current working directory - &status, // Put the exit status of the process in here - &signo, // Put the signal that caused the process to exit in here - &output, // Get the output from the command and place it in this - // string - std::chrono::seconds(3)); - if (status == 0 && !output.empty()) { - size_t first_non_newline = output.find_last_not_of("\r\n"); - if (first_non_newline != std::string::npos) { - output.erase(first_non_newline + 1); - } - output.append("/.."); - - g_xcode_filespec = CheckPathForXcode(FileSpec(output)); - } - } - } - }); - - return g_xcode_filespec; -} - -bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, - llvm::VersionTuple version) { - switch (sdk_type) { - case SDKType::MacOSX: - return version >= llvm::VersionTuple(10, 10); - case SDKType::iPhoneOS: - case SDKType::iPhoneSimulator: - return version >= llvm::VersionTuple(8); - } - - return false; -} - -bool PlatformDarwin::SDKSupportsModules(SDKType desired_type, - const FileSpec &sdk_path) { - ConstString last_path_component = sdk_path.GetLastPathComponent(); - - if (last_path_component) { - const llvm::StringRef sdk_name = last_path_component.GetStringRef(); - - if (!sdk_name.startswith(sdk_strings[desired_type])) - return false; - auto version_part = - sdk_name.drop_front(strlen(sdk_strings[desired_type])); - version_part.consume_back(".sdk"); - - llvm::VersionTuple version; - if (version.tryParse(version_part)) - return false; - return SDKSupportsModules(desired_type, version); - } - - return false; -} - -FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator( - void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) { - SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton); - - FileSpec spec(path); - if (SDKSupportsModules(enumerator_info->sdk_type, spec)) { - enumerator_info->found_path = spec; - return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; - } - - return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext; -} - -FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type, - const FileSpec &sdks_spec) { - // Look inside Xcode for the required installed iOS SDK version - - if (!FileSystem::Instance().IsDirectory(sdks_spec)) { - return FileSpec(); - } - - const bool find_directories = true; - const bool find_files = false; - const bool find_other = true; // include symlinks - - SDKEnumeratorInfo enumerator_info; - - enumerator_info.sdk_type = sdk_type; - - FileSystem::Instance().EnumerateDirectory( - sdks_spec.GetPath(), find_directories, find_files, find_other, - DirectoryEnumerator, &enumerator_info); - - if (FileSystem::Instance().IsDirectory(enumerator_info.found_path)) - return enumerator_info.found_path; - else - return FileSpec(); -} - -FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) { - switch (sdk_type) { - case SDKType::MacOSX: - case SDKType::iPhoneSimulator: - case SDKType::iPhoneOS: - break; - } - - FileSpec sdks_spec = GetXcodeContentsPath(); - sdks_spec.AppendPathComponent("Developer"); - sdks_spec.AppendPathComponent("Platforms"); - - switch (sdk_type) { - case SDKType::MacOSX: - sdks_spec.AppendPathComponent("MacOSX.platform"); - break; - case SDKType::iPhoneSimulator: - sdks_spec.AppendPathComponent("iPhoneSimulator.platform"); - break; - case SDKType::iPhoneOS: - sdks_spec.AppendPathComponent("iPhoneOS.platform"); - break; - } - - sdks_spec.AppendPathComponent("Developer"); - sdks_spec.AppendPathComponent("SDKs"); - - if (sdk_type == SDKType::MacOSX) { - llvm::VersionTuple version = HostInfo::GetOSVersion(); - - if (!version.empty()) { - if (SDKSupportsModules(SDKType::MacOSX, version)) { - // We slightly prefer the exact SDK for this machine. See if it is - // there. - - FileSpec native_sdk_spec = sdks_spec; - StreamString native_sdk_name; - native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(), - version.getMinor().getValueOr(0)); - native_sdk_spec.AppendPathComponent(native_sdk_name.GetString()); - - if (FileSystem::Instance().Exists(native_sdk_spec)) { - return native_sdk_spec; - } - } - } - } - - return FindSDKInXcodeForModules(sdk_type, sdks_spec); -} - -std::tuple<llvm::VersionTuple, llvm::StringRef> -PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) { - llvm::StringRef build; - llvm::StringRef version_str; - llvm::StringRef build_str; - std::tie(version_str, build_str) = dir.split(' '); - llvm::VersionTuple version; - if (!version.tryParse(version_str) || - build_str.empty()) { - if (build_str.consume_front("(")) { - size_t pos = build_str.find(')'); - build = build_str.slice(0, pos); - } - } - - return std::make_tuple(version, build); -} - -void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - Target *target, std::vector<std::string> &options, SDKType sdk_type) { - const std::vector<std::string> apple_arguments = { - "-x", "objective-c++", "-fobjc-arc", - "-fblocks", "-D_ISO646_H", "-D__ISO646_H"}; - - options.insert(options.end(), apple_arguments.begin(), apple_arguments.end()); - - StreamString minimum_version_option; - bool use_current_os_version = false; - switch (sdk_type) { - case SDKType::iPhoneOS: -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - use_current_os_version = true; -#else - use_current_os_version = false; -#endif - break; - - case SDKType::iPhoneSimulator: - use_current_os_version = false; - break; - - case SDKType::MacOSX: -#if defined(__i386__) || defined(__x86_64__) - use_current_os_version = true; -#else - use_current_os_version = false; -#endif - break; - } - - llvm::VersionTuple version; - if (use_current_os_version) - version = GetOSVersion(); - else if (target) { - // Our OS doesn't match our executable so we need to get the min OS version - // from the object file - ModuleSP exe_module_sp = target->GetExecutableModule(); - if (exe_module_sp) { - ObjectFile *object_file = exe_module_sp->GetObjectFile(); - if (object_file) - version = object_file->GetMinimumOSVersion(); - } - } - // Only add the version-min options if we got a version from somewhere - if (!version.empty()) { - switch (sdk_type) { - case SDKType::iPhoneOS: - minimum_version_option.PutCString("-mios-version-min="); - minimum_version_option.PutCString(version.getAsString()); - break; - case SDKType::iPhoneSimulator: - minimum_version_option.PutCString("-mios-simulator-version-min="); - minimum_version_option.PutCString(version.getAsString()); - break; - case SDKType::MacOSX: - minimum_version_option.PutCString("-mmacosx-version-min="); - minimum_version_option.PutCString(version.getAsString()); - } - options.push_back(minimum_version_option.GetString()); - } - - FileSpec sysroot_spec; - // Scope for mutex locker below - { - std::lock_guard<std::mutex> guard(m_mutex); - sysroot_spec = GetSDKDirectoryForModules(sdk_type); - } - - if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) { - options.push_back("-isysroot"); - options.push_back(sysroot_spec.GetPath()); - } -} - -ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) { - if (basename.IsEmpty()) - return basename; - - StreamString stream; - stream.Printf("lib%s.dylib", basename.GetCString()); - return ConstString(stream.GetString()); -} - -llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) { - if (process && strstr(GetPluginName().GetCString(), "-simulator")) { - lldb_private::ProcessInstanceInfo proc_info; - if (Host::GetProcessInfo(process->GetID(), proc_info)) { - const Environment &env = proc_info.GetEnvironment(); - - llvm::VersionTuple result; - if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION"))) - return result; - - std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH"); - if (!dyld_root_path.empty()) { - dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist"; - ApplePropertyList system_version_plist(dyld_root_path.c_str()); - std::string product_version; - if (system_version_plist.GetValueAsString("ProductVersion", - product_version)) { - if (!result.tryParse(product_version)) - return result; - } - } - } - // For simulator platforms, do NOT call back through - // Platform::GetOSVersion() as it might call Process::GetHostOSVersion() - // which we don't want as it will be incorrect - return llvm::VersionTuple(); - } - - return Platform::GetOSVersion(process); -} - -lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) { - // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled - // in with - // any executable directories that should be searched. - static std::vector<FileSpec> g_executable_dirs; - - // Find the global list of directories that we will search for executables - // once so we don't keep doing the work over and over. - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - - // When locating executables, trust the DEVELOPER_DIR first if it is set - FileSpec xcode_contents_dir = GetXcodeContentsPath(); - if (xcode_contents_dir) { - FileSpec xcode_lldb_resources = xcode_contents_dir; - xcode_lldb_resources.AppendPathComponent("SharedFrameworks"); - xcode_lldb_resources.AppendPathComponent("LLDB.framework"); - xcode_lldb_resources.AppendPathComponent("Resources"); - if (FileSystem::Instance().Exists(xcode_lldb_resources)) { - FileSpec dir; - dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str()); - g_executable_dirs.push_back(dir); - } - } - }); - - // Now search the global list of executable directories for the executable we - // are looking for - for (const auto &executable_dir : g_executable_dirs) { - FileSpec executable_file; - executable_file.GetDirectory() = executable_dir.GetDirectory(); - executable_file.GetFilename().SetCString(basename); - if (FileSystem::Instance().Exists(executable_file)) - return executable_file; - } - - return FileSpec(); -} - -lldb_private::Status -PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) { - // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if - // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require - // any specific value; rather, it just needs to exist). We will set it here - // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode - // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell - // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they - // specifically want it unset. - const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; - auto &env_vars = launch_info.GetEnvironment(); - if (!env_vars.count(disable_env_var)) { - // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get - // os_log and NSLog messages mirrored to the target process stderr. - env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable"); - } - - // Let our parent class do the real launching. - return PlatformPOSIX::LaunchProcess(launch_info); -} - -lldb_private::Status -PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec, Process *process, - ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, - ModuleSP *old_module_sp_ptr, bool *did_create_ptr) -{ - const FileSpec &platform_file = module_spec.GetFileSpec(); - // See if the file is present in any of the module_search_paths_ptr - // directories. - if (!module_sp && module_search_paths_ptr && platform_file) { - // create a vector of all the file / directory names in platform_file e.g. - // this might be - // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation - // - // We'll need to look in the module_search_paths_ptr directories for both - // "UIFoundation" and "UIFoundation.framework" -- most likely the latter - // will be the one we find there. - - FileSpec platform_pull_apart(platform_file); - std::vector<std::string> path_parts; - path_parts.push_back( - platform_pull_apart.GetLastPathComponent().AsCString()); - while (platform_pull_apart.RemoveLastPathComponent()) { - ConstString part = platform_pull_apart.GetLastPathComponent(); - path_parts.push_back(part.AsCString()); - } - const size_t path_parts_size = path_parts.size(); - - size_t num_module_search_paths = module_search_paths_ptr->GetSize(); - for (size_t i = 0; i < num_module_search_paths; ++i) { - Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log_verbose) - log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str()); - // Create a new FileSpec with this module_search_paths_ptr plus just the - // filename ("UIFoundation"), then the parent dir plus filename - // ("UIFoundation.framework/UIFoundation") etc - up to four names (to - // handle "Foo.framework/Contents/MacOS/Foo") - - for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) { - FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i)); - - // Add the components backwards. For - // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts - // is - // [0] UIFoundation - // [1] UIFoundation.framework - // [2] PrivateFrameworks - // - // and if 'j' is 2, we want to append path_parts[1] and then - // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the - // module_search_paths_ptr path. - - for (int k = j; k >= 0; --k) { - path_to_try.AppendPathComponent(path_parts[k]); - } - - if (FileSystem::Instance().Exists(path_to_try)) { - ModuleSpec new_module_spec(module_spec); - new_module_spec.GetFileSpec() = path_to_try; - Status new_error(Platform::GetSharedModule( - new_module_spec, process, module_sp, NULL, old_module_sp_ptr, - did_create_ptr)); - - if (module_sp) { - module_sp->SetPlatformFileSpec(path_to_try); - return new_error; - } - } - } - } - } - return Status(); -} diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h deleted file mode 100644 index f2dd9b1bc7782..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ /dev/null @@ -1,141 +0,0 @@ -//===-- PlatformDarwin.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformDarwin_h_ -#define liblldb_PlatformDarwin_h_ - - -#include "Plugins/Platform/POSIX/PlatformPOSIX.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Utility/FileSpec.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/FileSystem.h" - -#include <string> -#include <tuple> - -class PlatformDarwin : public PlatformPOSIX { -public: - PlatformDarwin(bool is_host); - - ~PlatformDarwin() override; - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - lldb_private::Status - ResolveSymbolFile(lldb_private::Target &target, - const lldb_private::ModuleSpec &sym_spec, - lldb_private::FileSpec &sym_file) override; - - lldb_private::FileSpecList LocateExecutableScriptingResources( - lldb_private::Target *target, lldb_private::Module &module, - lldb_private::Stream *feedback_stream) override; - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - size_t GetSoftwareBreakpointTrapOpcode( - lldb_private::Target &target, - lldb_private::BreakpointSite *bp_site) override; - - lldb::BreakpointSP - SetThreadCreationBreakpoint(lldb_private::Target &target) override; - - bool ModuleIsExcludedForUnconstrainedSearches( - lldb_private::Target &target, const lldb::ModuleSP &module_sp) override; - - bool ARMGetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch); - - bool x86GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch); - - int32_t GetResumeCountForLaunchInfo( - lldb_private::ProcessLaunchInfo &launch_info) override; - - void CalculateTrapHandlerSymbolNames() override; - - llvm::VersionTuple - GetOSVersion(lldb_private::Process *process = nullptr) override; - - bool SupportsModules() override { return true; } - - lldb_private::ConstString - GetFullNameForDylib(lldb_private::ConstString basename) override; - - lldb_private::FileSpec LocateExecutable(const char *basename) override; - - lldb_private::Status - LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - - static std::tuple<llvm::VersionTuple, llvm::StringRef> - ParseVersionBuildDir(llvm::StringRef str); - - enum SDKType : unsigned { - MacOSX = 0, - iPhoneSimulator, - iPhoneOS, - }; - -protected: - void ReadLibdispatchOffsetsAddress(lldb_private::Process *process); - - void ReadLibdispatchOffsets(lldb_private::Process *process); - - virtual lldb_private::Status GetSharedModuleWithLocalCache( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); - - static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version); - - static bool SDKSupportsModules(SDKType desired_type, - const lldb_private::FileSpec &sdk_path); - - struct SDKEnumeratorInfo { - lldb_private::FileSpec found_path; - SDKType sdk_type; - }; - - static lldb_private::FileSystem::EnumerateDirectoryResult - DirectoryEnumerator(void *baton, llvm::sys::fs::file_type file_type, - llvm::StringRef path); - - static lldb_private::FileSpec - FindSDKInXcodeForModules(SDKType sdk_type, - const lldb_private::FileSpec &sdks_spec); - - static lldb_private::FileSpec - GetSDKDirectoryForModules(PlatformDarwin::SDKType sdk_type); - - void - AddClangModuleCompilationOptionsForSDKType(lldb_private::Target *target, - std::vector<std::string> &options, - SDKType sdk_type); - - const char *GetDeveloperDirectory(); - - lldb_private::Status - FindBundleBinaryInExecSearchPaths (const lldb_private::ModuleSpec &module_spec, lldb_private::Process *process, - lldb::ModuleSP &module_sp, const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr); - - std::string m_developer_directory; - - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformDarwin); -}; - -#endif // liblldb_PlatformDarwin_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp deleted file mode 100644 index 4c6d9459e225f..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ /dev/null @@ -1,872 +0,0 @@ -//===-- PlatformDarwinKernel.cpp -----------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformDarwinKernel.h" - -#if defined(__APPLE__) // This Plugin uses the Mac-specific - // source/Host/macosx/cfcpp utilities - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Interpreter/OptionValueFileSpecList.h" -#include "lldb/Interpreter/OptionValueProperties.h" -#include "lldb/Interpreter/Property.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -#include "llvm/Support/FileSystem.h" - -#include <CoreFoundation/CoreFoundation.h> - -#include "Host/macosx/cfcpp/CFCBundle.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformDarwinKernel::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin(PlatformDarwinKernel::GetPluginNameStatic(), - PlatformDarwinKernel::GetDescriptionStatic(), - PlatformDarwinKernel::CreateInstance, - PlatformDarwinKernel::DebuggerInitialize); - } -} - -void PlatformDarwinKernel::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformDarwinKernel::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformDarwinKernel::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformDarwinKernel::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - // This is a special plugin that we don't want to activate just based on an - // ArchSpec for normal userland debugging. It is only useful in kernel debug - // sessions and the DynamicLoaderDarwinPlugin (or a user doing 'platform - // select') will force the creation of this Platform plugin. - if (!force) { - if (log) - log->Printf("PlatformDarwinKernel::%s() aborting creation of platform " - "because force == false", - __FUNCTION__); - return PlatformSP(); - } - - bool create = force; - LazyBool is_ios_debug_session = eLazyBoolCalculate; - - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::Apple: - create = true; - break; - - // Only accept "unknown" for vendor if the host is Apple and it "unknown" - // wasn't specified (it was just returned because it was NOT specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::WatchOS: - case llvm::Triple::TvOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - break; - // Only accept "vendor" for vendor if the host is Apple and it "unknown" - // wasn't specified (it was just returned because it was NOT specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; - default: - create = false; - break; - } - } - } - if (arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - is_ios_debug_session = eLazyBoolNo; - break; - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::thumb: - is_ios_debug_session = eLazyBoolYes; - break; - default: - is_ios_debug_session = eLazyBoolCalculate; - break; - } - } - if (create) { - if (log) - log->Printf("PlatformDarwinKernel::%s() creating platform", __FUNCTION__); - - return PlatformSP(new PlatformDarwinKernel(is_ios_debug_session)); - } - - if (log) - log->Printf("PlatformDarwinKernel::%s() aborting creation of platform", - __FUNCTION__); - - return PlatformSP(); -} - -lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() { - static ConstString g_name("darwin-kernel"); - return g_name; -} - -const char *PlatformDarwinKernel::GetDescriptionStatic() { - return "Darwin Kernel platform plug-in."; -} - -//------------------------------------------------------------------ -/// Code to handle the PlatformDarwinKernel settings -//------------------------------------------------------------------ - -static constexpr PropertyDefinition g_properties[] = { - {"search-locally-for-kexts", OptionValue::eTypeBoolean, true, true, NULL, - {}, "Automatically search for kexts on the local system when doing " - "kernel debugging."}, - {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, {}, - "Directories/KDKs to search for kexts in when starting a kernel debug " - "session."}}; - -enum { ePropertySearchForKexts = 0, ePropertyKextDirectories }; - -class PlatformDarwinKernelProperties : public Properties { -public: - static ConstString &GetSettingName() { - static ConstString g_setting_name("darwin-kernel"); - return g_setting_name; - } - - PlatformDarwinKernelProperties() : Properties() { - m_collection_sp.reset(new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } - - virtual ~PlatformDarwinKernelProperties() {} - - bool GetSearchForKexts() const { - const uint32_t idx = ePropertySearchForKexts; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - NULL, idx, g_properties[idx].default_uint_value != 0); - } - - FileSpecList &GetKextDirectories() const { - const uint32_t idx = ePropertyKextDirectories; - OptionValueFileSpecList *option_value = - m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList( - NULL, false, idx); - assert(option_value); - return option_value->GetCurrentValue(); - } -}; - -typedef std::shared_ptr<PlatformDarwinKernelProperties> - PlatformDarwinKernelPropertiesSP; - -static const PlatformDarwinKernelPropertiesSP &GetGlobalProperties() { - static PlatformDarwinKernelPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset(new PlatformDarwinKernelProperties()); - return g_settings_sp; -} - -void PlatformDarwinKernel::DebuggerInitialize( - lldb_private::Debugger &debugger) { - if (!PluginManager::GetSettingForPlatformPlugin( - debugger, PlatformDarwinKernelProperties::GetSettingName())) { - const bool is_global_setting = true; - PluginManager::CreateSettingForPlatformPlugin( - debugger, GetGlobalProperties()->GetValueProperties(), - ConstString("Properties for the PlatformDarwinKernel plug-in."), - is_global_setting); - } -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformDarwinKernel::PlatformDarwinKernel( - lldb_private::LazyBool is_ios_debug_session) - : PlatformDarwin(false), // This is a remote platform - m_name_to_kext_path_map_with_dsyms(), - m_name_to_kext_path_map_without_dsyms(), m_search_directories(), - m_search_directories_no_recursing(), m_kernel_binaries_with_dsyms(), - m_kernel_binaries_without_dsyms(), - m_ios_debug_session(is_ios_debug_session) - -{ - if (GetGlobalProperties()->GetSearchForKexts()) { - CollectKextAndKernelDirectories(); - SearchForKextsAndKernelsRecursively(); - } -} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformDarwinKernel::~PlatformDarwinKernel() {} - -void PlatformDarwinKernel::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - strm.Printf(" Debug session type: "); - if (m_ios_debug_session == eLazyBoolYes) - strm.Printf("iOS kernel debugging\n"); - else if (m_ios_debug_session == eLazyBoolNo) - strm.Printf("Mac OS X kernel debugging\n"); - else - strm.Printf("unknown kernel debugging\n"); - - strm.Printf("Directories searched recursively:\n"); - const uint32_t num_kext_dirs = m_search_directories.size(); - for (uint32_t i = 0; i < num_kext_dirs; ++i) { - strm.Printf("[%d] %s\n", i, m_search_directories[i].GetPath().c_str()); - } - - strm.Printf("Directories not searched recursively:\n"); - const uint32_t num_kext_dirs_no_recursion = - m_search_directories_no_recursing.size(); - for (uint32_t i = 0; i < num_kext_dirs_no_recursion; i++) { - strm.Printf("[%d] %s\n", i, - m_search_directories_no_recursing[i].GetPath().c_str()); - } - - strm.Printf(" Number of kexts with dSYMs indexed: %d\n", - (int)m_name_to_kext_path_map_with_dsyms.size()); - strm.Printf(" Number of kexts without dSYMs indexed: %d\n", - (int)m_name_to_kext_path_map_without_dsyms.size()); - strm.Printf(" Number of Kernel binaries with dSYMs indexed: %d\n", - (int)m_kernel_binaries_with_dsyms.size()); - strm.Printf(" Number of Kernel binaries without dSYMs indexed: %d\n", - (int)m_kernel_binaries_without_dsyms.size()); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - log->Printf("\nkexts with dSYMs"); - for (auto pos : m_name_to_kext_path_map_with_dsyms) { - log->Printf("%s", pos.second.GetPath().c_str()); - } - log->Printf("\nkexts without dSYMs"); - - for (auto pos : m_name_to_kext_path_map_without_dsyms) { - log->Printf("%s", pos.second.GetPath().c_str()); - } - log->Printf("\nkernels with dSYMS"); - for (auto fs : m_kernel_binaries_with_dsyms) { - log->Printf("%s", fs.GetPath().c_str()); - } - log->Printf("\nkernels without dSYMS"); - for (auto fs : m_kernel_binaries_without_dsyms) { - log->Printf("%s", fs.GetPath().c_str()); - } - log->Printf("\n"); - } -} - -// Populate the m_search_directories vector with directories we should search -// for kernel & kext binaries. - -void PlatformDarwinKernel::CollectKextAndKernelDirectories() { - // Differentiate between "ios debug session" and "mac debug session" so we - // don't index kext bundles that won't be used in this debug session. If - // this is an ios kext debug session, looking in /System/Library/Extensions - // is a waste of stat()s, for example. - - // DeveloperDirectory is something like - // "/Applications/Xcode.app/Contents/Developer" - std::string developer_dir = GetDeveloperDirectory(); - if (developer_dir.empty()) - developer_dir = "/Applications/Xcode.app/Contents/Developer"; - - if (m_ios_debug_session != eLazyBoolNo) { - AddSDKSubdirsToSearchPaths(developer_dir + - "/Platforms/iPhoneOS.platform/Developer/SDKs"); - AddSDKSubdirsToSearchPaths(developer_dir + - "/Platforms/AppleTVOS.platform/Developer/SDKs"); - AddSDKSubdirsToSearchPaths(developer_dir + - "/Platforms/WatchOS.platform/Developer/SDKs"); - AddSDKSubdirsToSearchPaths(developer_dir + - "/Platforms/BridgeOS.platform/Developer/SDKs"); - } - if (m_ios_debug_session != eLazyBoolYes) { - AddSDKSubdirsToSearchPaths(developer_dir + - "/Platforms/MacOSX.platform/Developer/SDKs"); - } - - AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit"); - AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs"); - // The KDKs distributed from Apple installed on external developer systems - // may be in directories like /Library/Developer/KDKs/KDK_10.10_14A298i.kdk - AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs"); - - if (m_ios_debug_session != eLazyBoolNo) { - } - if (m_ios_debug_session != eLazyBoolYes) { - AddRootSubdirsToSearchPaths(this, "/"); - } - - GetUserSpecifiedDirectoriesToSearch(); - - // Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols - FileSpec possible_dir(developer_dir + "/../Symbols"); - FileSystem::Instance().Resolve(possible_dir); - if (FileSystem::Instance().IsDirectory(possible_dir)) - m_search_directories.push_back(possible_dir); - - // Add simple directory of the current working directory - FileSpec cwd("."); - FileSystem::Instance().Resolve(cwd); - m_search_directories_no_recursing.push_back(cwd); -} - -void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() { - FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); - std::vector<FileSpec> possible_sdk_dirs; - - const uint32_t user_dirs_count = user_dirs.GetSize(); - for (uint32_t i = 0; i < user_dirs_count; i++) { - FileSpec dir = user_dirs.GetFileSpecAtIndex(i); - FileSystem::Instance().Resolve(dir); - if (FileSystem::Instance().IsDirectory(dir)) { - m_search_directories.push_back(dir); - } - } -} - -void PlatformDarwinKernel::AddRootSubdirsToSearchPaths( - PlatformDarwinKernel *thisp, const std::string &dir) { - const char *subdirs[] = { - "/System/Library/Extensions", "/Library/Extensions", - "/System/Library/Kernels", - "/System/Library/Extensions/KDK", // this one probably only exist in - // /AppleInternal/Developer/KDKs/*.kdk/... - nullptr}; - for (int i = 0; subdirs[i] != nullptr; i++) { - FileSpec testdir(dir + subdirs[i]); - FileSystem::Instance().Resolve(testdir); - if (FileSystem::Instance().IsDirectory(testdir)) - thisp->m_search_directories.push_back(testdir); - } - - // Look for kernel binaries in the top level directory, without any recursion - thisp->m_search_directories_no_recursing.push_back(FileSpec(dir + "/")); -} - -// Given a directory path dir, look for any subdirs named *.kdk and *.sdk -void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) { - // Look for *.kdk and *.sdk in dir - const bool find_directories = true; - const bool find_files = false; - const bool find_other = false; - FileSystem::Instance().EnumerateDirectory( - dir.c_str(), find_directories, find_files, find_other, - FindKDKandSDKDirectoriesInDirectory, this); -} - -// Helper function to find *.sdk and *.kdk directories in a given directory. -FileSystem::EnumerateDirectoryResult -PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory( - void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { - static ConstString g_sdk_suffix = ConstString(".sdk"); - static ConstString g_kdk_suffix = ConstString(".kdk"); - - PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton; - FileSpec file_spec(path); - if (ft == llvm::sys::fs::file_type::directory_file && - (file_spec.GetFileNameExtension() == g_sdk_suffix || - file_spec.GetFileNameExtension() == g_kdk_suffix)) { - AddRootSubdirsToSearchPaths(thisp, file_spec.GetPath()); - } - return FileSystem::eEnumerateDirectoryResultNext; -} - -// Recursively search trough m_search_directories looking for kext and kernel -// binaries, adding files found to the appropriate lists. -void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() { - const uint32_t num_dirs = m_search_directories.size(); - for (uint32_t i = 0; i < num_dirs; i++) { - const FileSpec &dir = m_search_directories[i]; - const bool find_directories = true; - const bool find_files = true; - const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. - FileSystem::Instance().EnumerateDirectory( - dir.GetPath().c_str(), find_directories, find_files, find_other, - GetKernelsAndKextsInDirectoryWithRecursion, this); - } - const uint32_t num_dirs_no_recurse = m_search_directories_no_recursing.size(); - for (uint32_t i = 0; i < num_dirs_no_recurse; i++) { - const FileSpec &dir = m_search_directories_no_recursing[i]; - const bool find_directories = true; - const bool find_files = true; - const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s. - FileSystem::Instance().EnumerateDirectory( - dir.GetPath().c_str(), find_directories, find_files, find_other, - GetKernelsAndKextsInDirectoryNoRecursion, this); - } -} - -// We're only doing a filename match here. We won't try opening the file to -// see if it's really a kernel or not until we need to find a kernel of a given -// UUID. There's no cheap way to find the UUID of a file (or if it's a Mach-O -// binary at all) without creating a whole Module for the file and throwing it -// away if it's not wanted. -// -// Recurse into any subdirectories found. - -FileSystem::EnumerateDirectoryResult -PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion( - void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { - return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, true); -} - -FileSystem::EnumerateDirectoryResult -PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion( - void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { - return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, false); -} - -FileSystem::EnumerateDirectoryResult -PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper( - void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path, - bool recurse) { - static ConstString g_kext_suffix = ConstString(".kext"); - static ConstString g_dsym_suffix = ConstString(".dSYM"); - static ConstString g_bundle_suffix = ConstString("Bundle"); - - FileSpec file_spec(path); - ConstString file_spec_extension = file_spec.GetFileNameExtension(); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - Log *log_verbose(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM | LLDB_LOG_OPTION_VERBOSE)); - - if (log_verbose) - log_verbose->Printf ("PlatformDarwinKernel examining '%s'", file_spec.GetPath().c_str()); - - PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton; - if (ft == llvm::sys::fs::file_type::regular_file || - ft == llvm::sys::fs::file_type::symlink_file) { - ConstString filename = file_spec.GetFilename(); - if ((strncmp(filename.GetCString(), "kernel", 6) == 0 || - strncmp(filename.GetCString(), "mach", 4) == 0) && - file_spec_extension != g_dsym_suffix) { - if (KernelHasdSYMSibling(file_spec)) - { - if (log) - { - log->Printf ("PlatformDarwinKernel registering kernel binary '%s' with dSYM sibling", file_spec.GetPath().c_str()); - } - thisp->m_kernel_binaries_with_dsyms.push_back(file_spec); - } - else - { - if (log) - { - log->Printf ("PlatformDarwinKernel registering kernel binary '%s', no dSYM", file_spec.GetPath().c_str()); - } - thisp->m_kernel_binaries_without_dsyms.push_back(file_spec); - } - return FileSystem::eEnumerateDirectoryResultNext; - } - } else if (ft == llvm::sys::fs::file_type::directory_file && - file_spec_extension == g_kext_suffix) { - AddKextToMap(thisp, file_spec); - // Look to see if there is a PlugIns subdir with more kexts - FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns"); - std::string search_here_too; - if (FileSystem::Instance().IsDirectory(contents_plugins)) { - search_here_too = contents_plugins.GetPath(); - } else { - FileSpec plugins(file_spec.GetPath() + "/PlugIns"); - if (FileSystem::Instance().IsDirectory(plugins)) { - search_here_too = plugins.GetPath(); - } - } - - if (!search_here_too.empty()) { - const bool find_directories = true; - const bool find_files = false; - const bool find_other = false; - FileSystem::Instance().EnumerateDirectory( - search_here_too.c_str(), find_directories, find_files, find_other, - recurse ? GetKernelsAndKextsInDirectoryWithRecursion - : GetKernelsAndKextsInDirectoryNoRecursion, - baton); - } - return FileSystem::eEnumerateDirectoryResultNext; - } - // Don't recurse into dSYM/kext/bundle directories - if (recurse && file_spec_extension != g_dsym_suffix && - file_spec_extension != g_kext_suffix && - file_spec_extension != g_bundle_suffix) { - if (log_verbose) - log_verbose->Printf ("PlatformDarwinKernel descending into directory '%s'", file_spec.GetPath().c_str()); - return FileSystem::eEnumerateDirectoryResultEnter; - } else { - return FileSystem::eEnumerateDirectoryResultNext; - } -} - -void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp, - const FileSpec &file_spec) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - CFCBundle bundle(file_spec.GetPath().c_str()); - CFStringRef bundle_id(bundle.GetIdentifier()); - if (bundle_id && CFGetTypeID(bundle_id) == CFStringGetTypeID()) { - char bundle_id_buf[PATH_MAX]; - if (CFStringGetCString(bundle_id, bundle_id_buf, sizeof(bundle_id_buf), - kCFStringEncodingUTF8)) { - ConstString bundle_conststr(bundle_id_buf); - if (KextHasdSYMSibling(file_spec)) - { - if (log) - { - log->Printf ("PlatformDarwinKernel registering kext binary '%s' with dSYM sibling", file_spec.GetPath().c_str()); - } - thisp->m_name_to_kext_path_map_with_dsyms.insert( - std::pair<ConstString, FileSpec>(bundle_conststr, file_spec)); - } - else - { - if (log) - { - log->Printf ("PlatformDarwinKernel registering kext binary '%s', no dSYM", file_spec.GetPath().c_str()); - } - thisp->m_name_to_kext_path_map_without_dsyms.insert( - std::pair<ConstString, FileSpec>(bundle_conststr, file_spec)); - } - } - } -} - -// Given a FileSpec of /dir/dir/foo.kext -// Return true if any of these exist: -// /dir/dir/foo.kext.dSYM -// /dir/dir/foo.kext/Contents/MacOS/foo.dSYM -// /dir/dir/foo.kext/foo.dSYM -bool PlatformDarwinKernel::KextHasdSYMSibling( - const FileSpec &kext_bundle_filepath) { - FileSpec dsym_fspec = kext_bundle_filepath; - std::string filename = dsym_fspec.GetFilename().AsCString(); - filename += ".dSYM"; - dsym_fspec.GetFilename() = ConstString(filename); - if (FileSystem::Instance().IsDirectory(dsym_fspec)) { - return true; - } - // Should probably get the CFBundleExecutable here or call - // CFBundleCopyExecutableURL - - // Look for a deep bundle foramt - ConstString executable_name = - kext_bundle_filepath.GetFileNameStrippingExtension(); - std::string deep_bundle_str = - kext_bundle_filepath.GetPath() + "/Contents/MacOS/"; - deep_bundle_str += executable_name.AsCString(); - deep_bundle_str += ".dSYM"; - dsym_fspec.SetFile(deep_bundle_str, FileSpec::Style::native); - FileSystem::Instance().Resolve(dsym_fspec); - if (FileSystem::Instance().IsDirectory(dsym_fspec)) { - return true; - } - - // look for a shallow bundle format - // - std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/"; - shallow_bundle_str += executable_name.AsCString(); - shallow_bundle_str += ".dSYM"; - dsym_fspec.SetFile(shallow_bundle_str, FileSpec::Style::native); - FileSystem::Instance().Resolve(dsym_fspec); - return FileSystem::Instance().IsDirectory(dsym_fspec); -} - -// Given a FileSpec of /dir/dir/mach.development.t7004 Return true if a dSYM -// exists next to it: -// /dir/dir/mach.development.t7004.dSYM -bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) { - FileSpec kernel_dsym = kernel_binary; - std::string filename = kernel_binary.GetFilename().AsCString(); - filename += ".dSYM"; - kernel_dsym.GetFilename() = ConstString(filename); - return FileSystem::Instance().IsDirectory(kernel_dsym); -} - -Status PlatformDarwinKernel::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - Status error; - module_sp.reset(); - const FileSpec &platform_file = module_spec.GetFileSpec(); - - // Treat the file's path as a kext bundle ID (e.g. - // "com.apple.driver.AppleIRController") and search our kext index. - std::string kext_bundle_id = platform_file.GetPath(); - if (!kext_bundle_id.empty()) { - ConstString kext_bundle_cs(kext_bundle_id.c_str()); - - // First look through the kext bundles that had a dsym next to them - if (m_name_to_kext_path_map_with_dsyms.count(kext_bundle_cs) > 0) { - for (BundleIDToKextIterator it = - m_name_to_kext_path_map_with_dsyms.begin(); - it != m_name_to_kext_path_map_with_dsyms.end(); ++it) { - if (it->first == kext_bundle_cs) { - error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(), - module_spec.GetArchitecture(), - module_sp); - if (module_sp.get()) { - return error; - } - } - } - } - - // Give the generic methods, including possibly calling into DebugSymbols - // framework on macOS systems, a chance. - error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - if (error.Success() && module_sp.get()) { - return error; - } - - // Lastly, look through the kext binarys without dSYMs - if (m_name_to_kext_path_map_without_dsyms.count(kext_bundle_cs) > 0) { - for (BundleIDToKextIterator it = - m_name_to_kext_path_map_without_dsyms.begin(); - it != m_name_to_kext_path_map_without_dsyms.end(); ++it) { - if (it->first == kext_bundle_cs) { - error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(), - module_spec.GetArchitecture(), - module_sp); - if (module_sp.get()) { - return error; - } - } - } - } - } - - if (kext_bundle_id == "mach_kernel" && module_spec.GetUUID().IsValid()) { - // First try all kernel binaries that have a dSYM next to them - for (auto possible_kernel : m_kernel_binaries_with_dsyms) { - if (FileSystem::Instance().Exists(possible_kernel)) { - ModuleSpec kern_spec(possible_kernel); - kern_spec.GetUUID() = module_spec.GetUUID(); - ModuleSP module_sp(new Module(kern_spec)); - if (module_sp && module_sp->GetObjectFile() && - module_sp->MatchesModuleSpec(kern_spec)) { - // module_sp is an actual kernel binary we want to add. - if (process) { - process->GetTarget().GetImages().AppendIfNeeded(module_sp); - error.Clear(); - return error; - } else { - error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL, - NULL, NULL); - if (module_sp && module_sp->GetObjectFile() && - module_sp->GetObjectFile()->GetType() != - ObjectFile::Type::eTypeCoreFile) { - return error; - } - module_sp.reset(); - } - } - } - } - - // Give the generic methods, including possibly calling into DebugSymbols - // framework on macOS systems, a chance. - error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - if (error.Success() && module_sp.get()) { - return error; - } - - // Next try all kernel binaries that don't have a dSYM - for (auto possible_kernel : m_kernel_binaries_without_dsyms) { - if (FileSystem::Instance().Exists(possible_kernel)) { - ModuleSpec kern_spec(possible_kernel); - kern_spec.GetUUID() = module_spec.GetUUID(); - ModuleSP module_sp(new Module(kern_spec)); - if (module_sp && module_sp->GetObjectFile() && - module_sp->MatchesModuleSpec(kern_spec)) { - // module_sp is an actual kernel binary we want to add. - if (process) { - process->GetTarget().GetImages().AppendIfNeeded(module_sp); - error.Clear(); - return error; - } else { - error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL, - NULL, NULL); - if (module_sp && module_sp->GetObjectFile() && - module_sp->GetObjectFile()->GetType() != - ObjectFile::Type::eTypeCoreFile) { - return error; - } - module_sp.reset(); - } - } - } - } - } - - return error; -} - -std::vector<lldb_private::FileSpec> -PlatformDarwinKernel::SearchForExecutablesRecursively(const std::string &dir) { - std::vector<FileSpec> executables; - std::error_code EC; - for (llvm::sys::fs::recursive_directory_iterator it(dir.c_str(), EC), - end; - it != end && !EC; it.increment(EC)) { - auto status = it->status(); - if (!status) - break; - if (llvm::sys::fs::is_regular_file(*status) && - llvm::sys::fs::can_execute(it->path())) - executables.emplace_back(it->path()); - } - return executables; -} - -Status PlatformDarwinKernel::ExamineKextForMatchingUUID( - const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, - const ArchSpec &arch, ModuleSP &exe_module_sp) { - for (const auto &exe_file : - SearchForExecutablesRecursively(kext_bundle_path.GetPath())) { - if (FileSystem::Instance().Exists(exe_file)) { - ModuleSpec exe_spec(exe_file); - exe_spec.GetUUID() = uuid; - if (!uuid.IsValid()) { - exe_spec.GetArchitecture() = arch; - } - - // First try to create a ModuleSP with the file / arch and see if the UUID - // matches. If that fails (this exec file doesn't have the correct uuid), - // don't call GetSharedModule (which may call in to the DebugSymbols - // framework and therefore can be slow.) - ModuleSP module_sp(new Module(exe_spec)); - if (module_sp && module_sp->GetObjectFile() && - module_sp->MatchesModuleSpec(exe_spec)) { - Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, - NULL, NULL, NULL); - if (exe_module_sp && exe_module_sp->GetObjectFile()) { - return error; - } - } - exe_module_sp.reset(); - } - } - - return {}; -} - -bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - return ARMGetSupportedArchitectureAtIndex(idx, arch); -#else - return x86GetSupportedArchitectureAtIndex(idx, arch); -#endif -} - -void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() { - m_trap_handlers.push_back(ConstString("trap_from_kernel")); - m_trap_handlers.push_back(ConstString("hndl_machine_check")); - m_trap_handlers.push_back(ConstString("hndl_double_fault")); - m_trap_handlers.push_back(ConstString("hndl_allintrs")); - m_trap_handlers.push_back(ConstString("hndl_alltraps")); - m_trap_handlers.push_back(ConstString("interrupt")); - m_trap_handlers.push_back(ConstString("fleh_prefabt")); - m_trap_handlers.push_back(ConstString("ExceptionVectorsBase")); - m_trap_handlers.push_back(ConstString("ExceptionVectorsTable")); - m_trap_handlers.push_back(ConstString("fleh_undef")); - m_trap_handlers.push_back(ConstString("fleh_dataabt")); - m_trap_handlers.push_back(ConstString("fleh_irq")); - m_trap_handlers.push_back(ConstString("fleh_decirq")); - m_trap_handlers.push_back(ConstString("fleh_fiq_generic")); - m_trap_handlers.push_back(ConstString("fleh_dec")); -} - -#else // __APPLE__ - -// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies -// on PlatformDarwinKernel for the plug-in name, we compile just the plug-in -// name in here to avoid issues. We are tracking an internal bug to resolve -// this issue by either not compiling in DynamicLoaderDarwinKernel for non- -// apple builds, or to make PlatformDarwinKernel build on all systems. -// PlatformDarwinKernel is currently not compiled on other platforms due to the -// use of the Mac-specific source/Host/macosx/cfcpp utilities. - -lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() { - static lldb_private::ConstString g_name("darwin-kernel"); - return g_name; -} - -#endif // __APPLE__ diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h deleted file mode 100644 index 201c3dff17954..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h +++ /dev/null @@ -1,208 +0,0 @@ -//===-- PlatformDarwinKernel.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformDarwinKernel_h_ -#define liblldb_PlatformDarwinKernel_h_ - -#include "lldb/Utility/ConstString.h" - -#if defined(__APPLE__) // This Plugin uses the Mac-specific - // source/Host/macosx/cfcpp utilities - -#include "lldb/Utility/FileSpec.h" - -#include "llvm/Support/FileSystem.h" - -#include "PlatformDarwin.h" - -class PlatformDarwinKernel : public PlatformDarwin { -public: - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void DebuggerInitialize(lldb_private::Debugger &debugger); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // Class Methods - //------------------------------------------------------------ - PlatformDarwinKernel(lldb_private::LazyBool is_ios_debug_session); - - virtual ~PlatformDarwinKernel(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - const char *GetDescription() override { return GetDescriptionStatic(); } - - void GetStatus(lldb_private::Stream &strm) override; - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - bool SupportsModules() override { return false; } - - void CalculateTrapHandlerSymbolNames() override; - -protected: - // Map from kext bundle ID ("com.apple.filesystems.exfat") to FileSpec for the - // kext bundle on - // the host ("/System/Library/Extensions/exfat.kext/Contents/Info.plist"). - typedef std::multimap<lldb_private::ConstString, lldb_private::FileSpec> - BundleIDToKextMap; - typedef BundleIDToKextMap::iterator BundleIDToKextIterator; - - typedef std::vector<lldb_private::FileSpec> KernelBinaryCollection; - - // Array of directories that were searched for kext bundles (used only for - // reporting to user) - typedef std::vector<lldb_private::FileSpec> DirectoriesSearchedCollection; - typedef DirectoriesSearchedCollection::iterator DirectoriesSearchedIterator; - - // Populate m_search_directories and m_search_directories_no_recursing vectors - // of directories - void CollectKextAndKernelDirectories(); - - void GetUserSpecifiedDirectoriesToSearch(); - - static void AddRootSubdirsToSearchPaths(PlatformDarwinKernel *thisp, - const std::string &dir); - - void AddSDKSubdirsToSearchPaths(const std::string &dir); - - static lldb_private::FileSystem::EnumerateDirectoryResult - FindKDKandSDKDirectoriesInDirectory(void *baton, llvm::sys::fs::file_type ft, - llvm::StringRef path); - - void SearchForKextsAndKernelsRecursively(); - - static lldb_private::FileSystem::EnumerateDirectoryResult - GetKernelsAndKextsInDirectoryWithRecursion(void *baton, - llvm::sys::fs::file_type ft, - llvm::StringRef path); - - static lldb_private::FileSystem::EnumerateDirectoryResult - GetKernelsAndKextsInDirectoryNoRecursion(void *baton, - llvm::sys::fs::file_type ft, - llvm::StringRef path); - - static lldb_private::FileSystem::EnumerateDirectoryResult - GetKernelsAndKextsInDirectoryHelper(void *baton, llvm::sys::fs::file_type ft, - llvm::StringRef path, bool recurse); - - static std::vector<lldb_private::FileSpec> - SearchForExecutablesRecursively(const std::string &dir); - - static void AddKextToMap(PlatformDarwinKernel *thisp, - const lldb_private::FileSpec &file_spec); - - // Returns true if there is a .dSYM bundle next to the kext, or next to the - // binary inside the kext. - static bool - KextHasdSYMSibling(const lldb_private::FileSpec &kext_bundle_filepath); - - // Returns true if there is a .dSYM bundle next to the kernel - static bool - KernelHasdSYMSibling(const lldb_private::FileSpec &kext_bundle_filepath); - - lldb_private::Status - ExamineKextForMatchingUUID(const lldb_private::FileSpec &kext_bundle_path, - const lldb_private::UUID &uuid, - const lldb_private::ArchSpec &arch, - lldb::ModuleSP &exe_module_sp); - - // Most of the ivars are assembled under FileSystem::EnumerateDirectory calls - // where the - // function being called for each file/directory must be static. We'll pass a - // this pointer - // as a baton and access the ivars directly. Toss-up whether this should just - // be a struct - // at this point. - -public: - BundleIDToKextMap m_name_to_kext_path_map_with_dsyms; // multimap of - // CFBundleID to - // FileSpec on local - // filesystem, kexts - // with dSYMs next to - // them - BundleIDToKextMap m_name_to_kext_path_map_without_dsyms; // multimap of - // CFBundleID to - // FileSpec on local - // filesystem, kexts - // without dSYMs next - // to them - DirectoriesSearchedCollection - m_search_directories; // list of directories we search for kexts/kernels - DirectoriesSearchedCollection - m_search_directories_no_recursing; // list of directories we search for - // kexts/kernels, no recursion - KernelBinaryCollection m_kernel_binaries_with_dsyms; // list of kernel - // binaries we found on - // local filesystem, - // without dSYMs next to - // them - KernelBinaryCollection m_kernel_binaries_without_dsyms; // list of kernel - // binaries we found - // on local - // filesystem, with - // dSYMs next to them - lldb_private::LazyBool m_ios_debug_session; - - DISALLOW_COPY_AND_ASSIGN(PlatformDarwinKernel); -}; - -#else // __APPLE__ - -// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on -// PlatformDarwinKernel for the plug-in name, we compile just the plug-in name -// in -// here to avoid issues. We are tracking an internal bug to resolve this issue -// by -// either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to -// make -// PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently -// not -// compiled on other platforms due to the use of the Mac-specific -// source/Host/macosx/cfcpp utilities. - -class PlatformDarwinKernel { -public: - static lldb_private::ConstString GetPluginNameStatic(); -}; - -#endif // __APPLE__ - -#endif // liblldb_PlatformDarwinKernel_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp deleted file mode 100644 index 4117231c308a7..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ /dev/null @@ -1,343 +0,0 @@ -//===-- PlatformMacOSX.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformMacOSX.h" -#include "lldb/Host/Config.h" - - -#include <sstream> - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -static uint32_t g_initialize_count = 0; - -void PlatformMacOSX::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { -#if defined(__APPLE__) - PlatformSP default_platform_sp(new PlatformMacOSX(true)); - default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetHostPlatform(default_platform_sp); -#endif - PluginManager::RegisterPlugin(PlatformMacOSX::GetPluginNameStatic(false), - PlatformMacOSX::GetDescriptionStatic(false), - PlatformMacOSX::CreateInstance); - } -} - -void PlatformMacOSX::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformMacOSX::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformMacOSX::%s(force=%s, arch={%s,%s})", __FUNCTION__, - force ? "true" : "false", arch_name, triple_cstr); - } - - // The only time we create an instance is when we are creating a remote - // macosx platform - const bool is_host = false; - - bool create = force; - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for vendor if the host is Apple and it "unknown" - // wasn't specified (it was just returned because it was NOT specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; -#endif - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::Darwin: // Deprecated, but still support Darwin for - // historical reasons - case llvm::Triple::MacOSX: - break; -#if defined(__APPLE__) - // Only accept "vendor" for vendor if the host is Apple and it "unknown" - // wasn't specified (it was just returned because it was NOT specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif - default: - create = false; - break; - } - } - } - if (create) { - if (log) - log->Printf("PlatformMacOSX::%s() creating platform", __FUNCTION__); - return PlatformSP(new PlatformMacOSX(is_host)); - } - - if (log) - log->Printf("PlatformMacOSX::%s() aborting creation of platform", - __FUNCTION__); - - return PlatformSP(); -} - -lldb_private::ConstString PlatformMacOSX::GetPluginNameStatic(bool is_host) { - if (is_host) { - static ConstString g_host_name(Platform::GetHostPlatformName()); - return g_host_name; - } else { - static ConstString g_remote_name("remote-macosx"); - return g_remote_name; - } -} - -const char *PlatformMacOSX::GetDescriptionStatic(bool is_host) { - if (is_host) - return "Local Mac OS X user platform plug-in."; - else - return "Remote Mac OS X user platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformMacOSX::PlatformMacOSX(bool is_host) : PlatformDarwin(is_host) {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformMacOSX::~PlatformMacOSX() {} - -ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) { - ModuleSP exe_module_sp(target.GetExecutableModule()); - if (exe_module_sp) { - ObjectFile *objfile = exe_module_sp->GetObjectFile(); - if (objfile) { - std::string xcode_contents_path; - std::string default_xcode_sdk; - FileSpec fspec; - uint32_t versions[2]; - if (objfile->GetSDKVersion(versions, sizeof(versions))) { - fspec = HostInfo::GetShlibDir(); - if (fspec) { - std::string path; - xcode_contents_path = fspec.GetPath(); - size_t pos = xcode_contents_path.find("/Xcode.app/Contents/"); - if (pos != std::string::npos) { - // LLDB.framework is inside an Xcode app bundle, we can locate the - // SDK from here - xcode_contents_path.erase(pos + strlen("/Xcode.app/Contents/")); - } else { - xcode_contents_path.clear(); - // Use the selected Xcode - int status = 0; - int signo = 0; - std::string output; - const char *command = "xcrun -sdk macosx --show-sdk-path"; - lldb_private::Status error = RunShellCommand( - command, // shell command to run - NULL, // current working directory - &status, // Put the exit status of the process in here - &signo, // Put the signal that caused the process to exit in - // here - &output, // Get the output from the command and place it in this - // string - std::chrono::seconds(3)); - if (status == 0 && !output.empty()) { - size_t first_non_newline = output.find_last_not_of("\r\n"); - if (first_non_newline != std::string::npos) - output.erase(first_non_newline + 1); - default_xcode_sdk = output; - - pos = default_xcode_sdk.find("/Xcode.app/Contents/"); - if (pos != std::string::npos) - xcode_contents_path = default_xcode_sdk.substr( - 0, pos + strlen("/Xcode.app/Contents/")); - } - } - } - - if (!xcode_contents_path.empty()) { - StreamString sdk_path; - sdk_path.Printf("%sDeveloper/Platforms/MacOSX.platform/Developer/" - "SDKs/MacOSX%u.%u.sdk", - xcode_contents_path.c_str(), versions[0], - versions[1]); - fspec.SetFile(sdk_path.GetString(), FileSpec::Style::native); - if (FileSystem::Instance().Exists(fspec)) - return ConstString(sdk_path.GetString()); - } - - if (!default_xcode_sdk.empty()) { - fspec.SetFile(default_xcode_sdk, FileSpec::Style::native); - if (FileSystem::Instance().Exists(fspec)) - return ConstString(default_xcode_sdk); - } - } - } - } - return ConstString(); -} - -Status PlatformMacOSX::GetSymbolFile(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - if (IsRemote()) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, - local_file); - } - - // Default to the local case - local_file = platform_file; - return Status(); -} - -lldb_private::Status -PlatformMacOSX::GetFileWithUUID(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file) { - if (IsRemote() && m_remote_platform_sp) { - std::string local_os_build; -#if !defined(__linux__) - HostInfo::GetOSBuildString(local_os_build); -#endif - std::string remote_os_build; - m_remote_platform_sp->GetOSBuildString(remote_os_build); - if (local_os_build == remote_os_build) { - // same OS version: the local file is good enough - local_file = platform_file; - return Status(); - } else { - // try to find the file in the cache - std::string cache_path(GetLocalCacheDirectory()); - std::string module_path(platform_file.GetPath()); - cache_path.append(module_path); - FileSpec module_cache_spec(cache_path); - if (FileSystem::Instance().Exists(module_cache_spec)) { - local_file = module_cache_spec; - return Status(); - } - // bring in the remote module file - FileSpec module_cache_folder = - module_cache_spec.CopyByRemovingLastPathComponent(); - // try to make the local directory first - Status err( - llvm::sys::fs::create_directory(module_cache_folder.GetPath())); - if (err.Fail()) - return err; - err = GetFile(platform_file, module_cache_spec); - if (err.Fail()) - return err; - if (FileSystem::Instance().Exists(module_cache_spec)) { - local_file = module_cache_spec; - return Status(); - } else - return Status("unable to obtain valid module file"); - } - } - local_file = platform_file; - return Status(); -} - -bool PlatformMacOSX::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - return ARMGetSupportedArchitectureAtIndex(idx, arch); -#else - return x86GetSupportedArchitectureAtIndex(idx, arch); -#endif -} - -lldb_private::Status PlatformMacOSX::GetSharedModule( - const lldb_private::ModuleSpec &module_spec, Process *process, - lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { - Status error = GetSharedModuleWithLocalCache( - module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr); - - if (module_sp) { - if (module_spec.GetArchitecture().GetCore() == - ArchSpec::eCore_x86_64_x86_64h) { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile == NULL) { - // We didn't find an x86_64h slice, fall back to a x86_64 slice - ModuleSpec module_spec_x86_64(module_spec); - module_spec_x86_64.GetArchitecture() = ArchSpec("x86_64-apple-macosx"); - lldb::ModuleSP x86_64_module_sp; - lldb::ModuleSP old_x86_64_module_sp; - bool did_create = false; - Status x86_64_error = GetSharedModuleWithLocalCache( - module_spec_x86_64, x86_64_module_sp, module_search_paths_ptr, - &old_x86_64_module_sp, &did_create); - if (x86_64_module_sp && x86_64_module_sp->GetObjectFile()) { - module_sp = x86_64_module_sp; - if (old_module_sp_ptr) - *old_module_sp_ptr = old_x86_64_module_sp; - if (did_create_ptr) - *did_create_ptr = did_create; - return x86_64_error; - } - } - } - } - - if (!module_sp) { - error = FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); - } - return error; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h deleted file mode 100644 index d08029a29f312..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h +++ /dev/null @@ -1,88 +0,0 @@ -//===-- PlatformMacOSX.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformMacOSX_h_ -#define liblldb_PlatformMacOSX_h_ - -#include "PlatformDarwin.h" - -class PlatformMacOSX : public PlatformDarwin { -public: - PlatformMacOSX(bool is_host); - - ~PlatformMacOSX() override; - - //------------------------------------------------------------ - // Class functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(bool is_host); - - static const char *GetDescriptionStatic(bool is_host); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(IsHost()); - } - - uint32_t GetPluginVersion() override { return 1; } - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - const char *GetDescription() override { - return GetDescriptionStatic(IsHost()); - } - - lldb_private::Status - GetSymbolFile(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file); - - lldb_private::Status - GetFile(const lldb_private::FileSpec &source, - const lldb_private::FileSpec &destination) override { - return PlatformDarwin::GetFile(source, destination); - } - - lldb_private::Status - GetFileWithUUID(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - lldb_private::ConstString - GetSDKDirectory(lldb_private::Target &target) override; - - void - AddClangModuleCompilationOptions(lldb_private::Target *target, - std::vector<std::string> &options) override { - return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::MacOSX); - } - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformMacOSX); -}; - -#endif // liblldb_PlatformMacOSX_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp deleted file mode 100644 index fd804d0aaeed0..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp +++ /dev/null @@ -1,186 +0,0 @@ -//===-- PlatformRemoteAppleBridge.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <string> -#include <vector> - -#include "PlatformRemoteAppleBridge.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteAppleBridge::PlatformRemoteAppleBridge() - : PlatformRemoteDarwinDevice () {} - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformRemoteAppleBridge::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin(PlatformRemoteAppleBridge::GetPluginNameStatic(), - PlatformRemoteAppleBridge::GetDescriptionStatic(), - PlatformRemoteAppleBridge::CreateInstance); - } -} - -void PlatformRemoteAppleBridge::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformRemoteAppleBridge::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformRemoteAppleBridge::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformRemoteAppleBridge::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::aarch64: { - const llvm::Triple &triple = arch->GetTriple(); - llvm::Triple::VendorType vendor = triple.getVendor(); - switch (vendor) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - -#endif - default: - break; - } - if (create) { - switch (triple.getOS()) { - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - break; - - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - - if (create) { - if (log) - log->Printf("PlatformRemoteAppleBridge::%s() creating platform", - __FUNCTION__); - - return lldb::PlatformSP(new PlatformRemoteAppleBridge()); - } - - if (log) - log->Printf("PlatformRemoteAppleBridge::%s() aborting creation of platform", - __FUNCTION__); - - return lldb::PlatformSP(); -} - -lldb_private::ConstString PlatformRemoteAppleBridge::GetPluginNameStatic() { - static ConstString g_name("remote-bridgeos"); - return g_name; -} - -const char *PlatformRemoteAppleBridge::GetDescriptionStatic() { - return "Remote BridgeOS platform plug-in."; -} - -bool PlatformRemoteAppleBridge::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - ArchSpec system_arch(GetSystemArchitecture()); - - const ArchSpec::Core system_core = system_arch.GetCore(); - switch (system_core) { - default: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-bridgeos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_arm64: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-bridgeos"); - return true; - default: - break; - } - break; - } - arch.Clear(); - return false; -} - - -void PlatformRemoteAppleBridge::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) -{ - dirnames.clear(); - dirnames.push_back("BridgeOS DeviceSupport"); -} - -std::string PlatformRemoteAppleBridge::GetPlatformName () -{ - return "BridgeOS.platform"; -} - diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h deleted file mode 100644 index 48f06eee3f019..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h +++ /dev/null @@ -1,73 +0,0 @@ -//===-- PlatformRemoteAppleBridge.h ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformRemoteAppleBridge_h_ -#define liblldb_PlatformRemoteAppleBridge_h_ - -#include <string> - -#include "lldb/Utility/FileSpec.h" - -#include "llvm/Support/FileSystem.h" - -#include "PlatformRemoteDarwinDevice.h" - -class PlatformRemoteAppleBridge : public PlatformRemoteDarwinDevice { -public: - PlatformRemoteAppleBridge(); - - ~PlatformRemoteAppleBridge() override = default; - - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - const char *GetDescription() override { return GetDescriptionStatic(); } - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - -protected: - - //------------------------------------------------------------ - // lldb_private::PlatformRemoteDarwinDevice functions - //------------------------------------------------------------ - - void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override; - - std::string GetPlatformName () override; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleBridge); -}; - -#endif // liblldb_PlatformRemoteAppleBridge_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp deleted file mode 100644 index 593e888898c42..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//===-- PlatformRemoteAppleTV.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <string> -#include <vector> - -#include "PlatformRemoteAppleTV.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteAppleTV::PlatformRemoteAppleTV() - : PlatformRemoteDarwinDevice () {} - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformRemoteAppleTV::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin(PlatformRemoteAppleTV::GetPluginNameStatic(), - PlatformRemoteAppleTV::GetDescriptionStatic(), - PlatformRemoteAppleTV::CreateInstance); - } -} - -void PlatformRemoteAppleTV::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformRemoteAppleTV::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformRemoteAppleTV::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformRemoteAppleTV::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::thumb: { - const llvm::Triple &triple = arch->GetTriple(); - llvm::Triple::VendorType vendor = triple.getVendor(); - switch (vendor) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - -#endif - default: - break; - } - if (create) { - switch (triple.getOS()) { - case llvm::Triple::TvOS: // This is the right triple value for Apple TV - // debugging - break; - - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - - if (create) { - if (log) - log->Printf("PlatformRemoteAppleTV::%s() creating platform", - __FUNCTION__); - - return lldb::PlatformSP(new PlatformRemoteAppleTV()); - } - - if (log) - log->Printf("PlatformRemoteAppleTV::%s() aborting creation of platform", - __FUNCTION__); - - return lldb::PlatformSP(); -} - -lldb_private::ConstString PlatformRemoteAppleTV::GetPluginNameStatic() { - static ConstString g_name("remote-tvos"); - return g_name; -} - -const char *PlatformRemoteAppleTV::GetDescriptionStatic() { - return "Remote Apple TV platform plug-in."; -} - -bool PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - ArchSpec system_arch(GetSystemArchitecture()); - - const ArchSpec::Core system_core = system_arch.GetCore(); - switch (system_core) { - default: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-tvos"); - return true; - case 1: - arch.SetTriple("armv7s-apple-tvos"); - return true; - case 2: - arch.SetTriple("armv7-apple-tvos"); - return true; - case 3: - arch.SetTriple("thumbv7s-apple-tvos"); - return true; - case 4: - arch.SetTriple("thumbv7-apple-tvos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_arm64: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-tvos"); - return true; - case 1: - arch.SetTriple("armv7s-apple-tvos"); - return true; - case 2: - arch.SetTriple("armv7-apple-tvos"); - return true; - case 3: - arch.SetTriple("thumbv7s-apple-tvos"); - return true; - case 4: - arch.SetTriple("thumbv7-apple-tvos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7s: - switch (idx) { - case 0: - arch.SetTriple("armv7s-apple-tvos"); - return true; - case 1: - arch.SetTriple("armv7-apple-tvos"); - return true; - case 2: - arch.SetTriple("thumbv7s-apple-tvos"); - return true; - case 3: - arch.SetTriple("thumbv7-apple-tvos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7: - switch (idx) { - case 0: - arch.SetTriple("armv7-apple-tvos"); - return true; - case 1: - arch.SetTriple("thumbv7-apple-tvos"); - return true; - default: - break; - } - break; - } - arch.Clear(); - return false; -} - - -void PlatformRemoteAppleTV::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) -{ - dirnames.clear(); - dirnames.push_back("tvOS DeviceSupport"); -} - -std::string PlatformRemoteAppleTV::GetPlatformName () -{ - return "AppleTVOS.platform"; -} - diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h deleted file mode 100644 index d8860a90a460b..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h +++ /dev/null @@ -1,73 +0,0 @@ -//===-- PlatformRemoteAppleTV.h ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformRemoteAppleTV_h_ -#define liblldb_PlatformRemoteAppleTV_h_ - -#include <string> - -#include "lldb/Utility/FileSpec.h" - -#include "llvm/Support/FileSystem.h" - -#include "PlatformRemoteDarwinDevice.h" - -class PlatformRemoteAppleTV : public PlatformRemoteDarwinDevice { -public: - PlatformRemoteAppleTV(); - - ~PlatformRemoteAppleTV() override = default; - - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - const char *GetDescription() override { return GetDescriptionStatic(); } - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - -protected: - - //------------------------------------------------------------ - // lldb_private::PlatformRemoteDarwinDevice functions - //------------------------------------------------------------ - - void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override; - - std::string GetPlatformName () override; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleTV); -}; - -#endif // liblldb_PlatformRemoteAppleTV_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp deleted file mode 100644 index 59e6e19fbffcc..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp +++ /dev/null @@ -1,303 +0,0 @@ -//===-- PlatformRemoteAppleWatch.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <string> -#include <vector> - -#include "PlatformRemoteAppleWatch.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformRemoteAppleWatch::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin( - PlatformRemoteAppleWatch::GetPluginNameStatic(), - PlatformRemoteAppleWatch::GetDescriptionStatic(), - PlatformRemoteAppleWatch::CreateInstance); - } -} - -void PlatformRemoteAppleWatch::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformRemoteAppleWatch::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformRemoteAppleWatch::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::thumb: { - const llvm::Triple &triple = arch->GetTriple(); - llvm::Triple::VendorType vendor = triple.getVendor(); - switch (vendor) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - -#endif - default: - break; - } - if (create) { - switch (triple.getOS()) { - case llvm::Triple::WatchOS: // This is the right triple value for Apple - // Watch debugging - break; - - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - -#if defined(__APPLE__) && \ - (defined(__arm__) || defined(__arm64__) || defined(__aarch64__)) - // If lldb is running on a watch, this isn't a RemoteWatch environment; it's - // a local system environment. - if (force == false) { - create = false; - } -#endif - - if (create) { - if (log) - log->Printf("PlatformRemoteAppleWatch::%s() creating platform", - __FUNCTION__); - - return lldb::PlatformSP(new PlatformRemoteAppleWatch()); - } - - if (log) - log->Printf("PlatformRemoteAppleWatch::%s() aborting creation of platform", - __FUNCTION__); - - return lldb::PlatformSP(); -} - -lldb_private::ConstString PlatformRemoteAppleWatch::GetPluginNameStatic() { - static ConstString g_name("remote-watchos"); - return g_name; -} - -const char *PlatformRemoteAppleWatch::GetDescriptionStatic() { - return "Remote Apple Watch platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteAppleWatch::PlatformRemoteAppleWatch() - : PlatformRemoteDarwinDevice() {} - -bool PlatformRemoteAppleWatch::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - ArchSpec system_arch(GetSystemArchitecture()); - - const ArchSpec::Core system_core = system_arch.GetCore(); - switch (system_core) { - default: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-watchos"); - return true; - case 1: - arch.SetTriple("armv7k-apple-watchos"); - return true; - case 2: - arch.SetTriple("armv7s-apple-watchos"); - return true; - case 3: - arch.SetTriple("armv7-apple-watchos"); - return true; - case 4: - arch.SetTriple("thumbv7k-apple-watchos"); - return true; - case 5: - arch.SetTriple("thumbv7-apple-watchos"); - return true; - case 6: - arch.SetTriple("thumbv7s-apple-watchos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_arm64: - switch (idx) { - case 0: - arch.SetTriple("arm64-apple-watchos"); - return true; - case 1: - arch.SetTriple("armv7k-apple-watchos"); - return true; - case 2: - arch.SetTriple("armv7s-apple-watchos"); - return true; - case 3: - arch.SetTriple("armv7-apple-watchos"); - return true; - case 4: - arch.SetTriple("thumbv7k-apple-watchos"); - return true; - case 5: - arch.SetTriple("thumbv7-apple-watchos"); - return true; - case 6: - arch.SetTriple("thumbv7s-apple-watchos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7k: - switch (idx) { - case 0: - arch.SetTriple("armv7k-apple-watchos"); - return true; - case 1: - arch.SetTriple("armv7s-apple-watchos"); - return true; - case 2: - arch.SetTriple("armv7-apple-watchos"); - return true; - case 3: - arch.SetTriple("thumbv7k-apple-watchos"); - return true; - case 4: - arch.SetTriple("thumbv7-apple-watchos"); - return true; - case 5: - arch.SetTriple("thumbv7s-apple-watchos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7s: - switch (idx) { - case 0: - arch.SetTriple("armv7s-apple-watchos"); - return true; - case 1: - arch.SetTriple("armv7k-apple-watchos"); - return true; - case 2: - arch.SetTriple("armv7-apple-watchos"); - return true; - case 3: - arch.SetTriple("thumbv7k-apple-watchos"); - return true; - case 4: - arch.SetTriple("thumbv7-apple-watchos"); - return true; - case 5: - arch.SetTriple("thumbv7s-apple-watchos"); - return true; - default: - break; - } - break; - - case ArchSpec::eCore_arm_armv7: - switch (idx) { - case 0: - arch.SetTriple("armv7-apple-watchos"); - return true; - case 1: - arch.SetTriple("armv7k-apple-watchos"); - return true; - case 2: - arch.SetTriple("thumbv7k-apple-watchos"); - return true; - case 3: - arch.SetTriple("thumbv7-apple-watchos"); - return true; - default: - break; - } - break; - } - arch.Clear(); - return false; -} - -void PlatformRemoteAppleWatch::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) -{ - dirnames.clear(); - dirnames.push_back("watchOS DeviceSupport"); -} - -std::string PlatformRemoteAppleWatch::GetPlatformName () -{ - return "WatchOS.platform"; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h deleted file mode 100644 index ed1cbea62e92f..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h +++ /dev/null @@ -1,78 +0,0 @@ -//===-- PlatformRemoteAppleWatch.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformRemoteAppleWatch_h_ -#define liblldb_PlatformRemoteAppleWatch_h_ - -#include <string> -#include <vector> - -#include "lldb/Utility/FileSpec.h" - -#include "PlatformRemoteDarwinDevice.h" - -#include "llvm/Support/FileSystem.h" - -class PlatformRemoteAppleWatch : public PlatformRemoteDarwinDevice { -public: - PlatformRemoteAppleWatch(); - - ~PlatformRemoteAppleWatch() override = default; - - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - const char *GetDescription() override { return GetDescriptionStatic(); } - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - -protected: - - //------------------------------------------------------------ - // lldb_private::PlatformRemoteDarwinDevice functions - //------------------------------------------------------------ - - void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override; - - std::string GetPlatformName () override; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleWatch); -}; - -#endif // liblldb_PlatformRemoteAppleWatch_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp deleted file mode 100644 index 511bfc20376b6..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ /dev/null @@ -1,661 +0,0 @@ -//===-- PlatformRemoteDarwinDevice.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformRemoteDarwinDevice.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( - const lldb_private::FileSpec &sdk_dir) - : directory(sdk_dir), build(), user_cached(false) { - llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); - llvm::StringRef build_str; - std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); - build.SetString(build_str); -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice() - : PlatformDarwin(false), // This is a remote platform - m_sdk_directory_infos(), m_device_support_directory(), - m_device_support_directory_for_os_version(), m_build_update(), - m_last_module_sdk_idx(UINT32_MAX), - m_connected_module_sdk_idx(UINT32_MAX) {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() {} - -void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); - if (sdk_directory) - strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); - else - strm.PutCString(" SDK Path: error: unable to locate SDK\n"); - - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - for (uint32_t i = 0; i < num_sdk_infos; ++i) { - const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; - strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i, - sdk_dir_info.directory.GetPath().c_str()); - } -} - -Status PlatformRemoteDarwinDevice::ResolveExecutable( - const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Status error; - // Nothing special to do here, just use the actual file and architecture - - ModuleSpec resolved_module_spec(ms); - - // Resolve any executable within a bundle on MacOSX - // TODO: verify that this handles shallow bundles, if not then implement one - // ourselves - Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); - - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { - if (resolved_module_spec.GetArchitecture().IsValid() || - resolved_module_spec.GetUUID().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - - if (exe_module_sp && exe_module_sp->GetObjectFile()) - return error; - exe_module_sp.reset(); - } - // No valid architecture was specified or the exact ARM slice wasn't found - // so ask the platform for the architectures that we should be using (in - // the correct order) and see if we can find a match that way - StreamString arch_names; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString( - resolved_module_spec.GetArchitecture().GetArchitectureName()); - } - - if (error.Fail() || !exe_module_sp) { - if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetData()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } else { - error.SetErrorStringWithFormat( - "'%s' does not exist", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - - return error; -} - -FileSystem::EnumerateDirectoryResult -PlatformRemoteDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback( - void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { - ((PlatformRemoteDarwinDevice::SDKDirectoryInfoCollection *)baton) - ->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(FileSpec(path))); - return FileSystem::eEnumerateDirectoryResultNext; -} - -bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - std::lock_guard<std::mutex> guard(m_sdk_dir_mutex); - if (m_sdk_directory_infos.empty()) { - // A --sysroot option was supplied - add it to our list of SDKs to check - if (m_sdk_sysroot) { - FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString()); - FileSystem::Instance().Resolve(sdk_sysroot_fspec); - const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec); - m_sdk_directory_infos.push_back(sdk_sysroot_directory_info); - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded added " - "--sysroot SDK directory %s", - m_sdk_sysroot.GetCString()); - } - return true; - } - const char *device_support_dir = GetDeviceSupportDirectory(); - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded Got " - "DeviceSupport directory %s", - device_support_dir); - } - if (device_support_dir) { - const bool find_directories = true; - const bool find_files = false; - const bool find_other = false; - - SDKDirectoryInfoCollection builtin_sdk_directory_infos; - FileSystem::Instance().EnumerateDirectory( - m_device_support_directory, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &builtin_sdk_directory_infos); - - // Only add SDK directories that have symbols in them, some SDKs only - // contain developer disk images and no symbols, so they aren't useful to - // us. - FileSpec sdk_symbols_symlink_fspec; - for (const auto &sdk_directory_info : builtin_sdk_directory_infos) { - sdk_symbols_symlink_fspec = sdk_directory_info.directory; - sdk_symbols_symlink_fspec.AppendPathComponent("Symbols"); - if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) { - m_sdk_directory_infos.push_back(sdk_directory_info); - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "added builtin SDK directory %s", - sdk_symbols_symlink_fspec.GetPath().c_str()); - } - } - } - - std::vector<std::string> device_support_dirnames; - GetDeviceSupportDirectoryNames (device_support_dirnames); - - for (std::string &dirname : device_support_dirnames) - { - const uint32_t num_installed = m_sdk_directory_infos.size(); - std::string local_sdk_cache_str = "~/Library/Developer/Xcode/"; - local_sdk_cache_str += dirname; - FileSpec local_sdk_cache(local_sdk_cache_str.c_str()); - FileSystem::Instance().Resolve(local_sdk_cache); - if (FileSystem::Instance().Exists(local_sdk_cache)) { - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "searching %s for additional SDKs", - local_sdk_cache.GetPath().c_str()); - } - char path[PATH_MAX]; - if (local_sdk_cache.GetPath(path, sizeof(path))) { - FileSystem::Instance().EnumerateDirectory( - path, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &m_sdk_directory_infos); - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - // First try for an exact match of major, minor and update - for (uint32_t i = num_installed; i < num_sdk_infos; ++i) { - m_sdk_directory_infos[i].user_cached = true; - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "user SDK directory %s", - m_sdk_directory_infos[i].directory.GetPath().c_str()); - } - } - } - } - } - - const char *addtional_platform_dirs = getenv("PLATFORM_SDK_DIRECTORY"); - if (addtional_platform_dirs) { - SDKDirectoryInfoCollection env_var_sdk_directory_infos; - FileSystem::Instance().EnumerateDirectory( - addtional_platform_dirs, find_directories, find_files, find_other, - GetContainedFilesIntoVectorOfStringsCallback, - &env_var_sdk_directory_infos); - FileSpec sdk_symbols_symlink_fspec; - for (const auto &sdk_directory_info : env_var_sdk_directory_infos) { - sdk_symbols_symlink_fspec = sdk_directory_info.directory; - sdk_symbols_symlink_fspec.AppendPathComponent("Symbols"); - if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) { - m_sdk_directory_infos.push_back(sdk_directory_info); - if (log) { - log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded " - "added env var SDK directory %s", - sdk_symbols_symlink_fspec.GetPath().c_str()); - } - } - } - } - - } - } - return !m_sdk_directory_infos.empty(); -} - -const PlatformRemoteDarwinDevice::SDKDirectoryInfo * -PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() { - uint32_t i; - if (UpdateSDKDirectoryInfosIfNeeded()) { - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - - // Check to see if the user specified a build string. If they did, then be - // sure to match it. - std::vector<bool> check_sdk_info(num_sdk_infos, true); - ConstString build(m_sdk_build); - if (build) { - for (i = 0; i < num_sdk_infos; ++i) - check_sdk_info[i] = m_sdk_directory_infos[i].build == build; - } - - // If we are connected we can find the version of the OS the platform us - // running on and select the right SDK - llvm::VersionTuple version = GetOSVersion(); - if (!version.empty()) { - if (UpdateSDKDirectoryInfosIfNeeded()) { - // First try for an exact match of major, minor and update - for (i = 0; i < num_sdk_infos; ++i) { - if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version == version) - return &m_sdk_directory_infos[i]; - } - } - // First try for an exact match of major and minor - for (i = 0; i < num_sdk_infos; ++i) { - if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version.getMajor() == - version.getMajor() && - m_sdk_directory_infos[i].version.getMinor() == - version.getMinor()) { - return &m_sdk_directory_infos[i]; - } - } - } - // Lastly try to match of major version only.. - for (i = 0; i < num_sdk_infos; ++i) { - if (check_sdk_info[i]) { - if (m_sdk_directory_infos[i].version.getMajor() == - version.getMajor()) { - return &m_sdk_directory_infos[i]; - } - } - } - } - } else if (build) { - // No version, just a build number, search for the first one that matches - for (i = 0; i < num_sdk_infos; ++i) - if (check_sdk_info[i]) - return &m_sdk_directory_infos[i]; - } - } - return NULL; -} - -const PlatformRemoteDarwinDevice::SDKDirectoryInfo * -PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() { - const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL; - if (UpdateSDKDirectoryInfosIfNeeded()) { - auto max = std::max_element( - m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(), - [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) { - return a.version < b.version; - }); - if (max != m_sdk_directory_infos.end()) - result = &*max; - } - return result; -} - -const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectory() { - std::string platform_dir = "/Platforms/" + GetPlatformName() + "/DeviceSupport"; - if (m_device_support_directory.empty()) { - const char *device_support_dir = GetDeveloperDirectory(); - if (device_support_dir) { - m_device_support_directory.assign(device_support_dir); - m_device_support_directory.append(platform_dir.c_str()); - } else { - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_device_support_directory.assign(1, '\0'); - } - } - // We should have put a single NULL character into m_device_support_directory - // or it should have a valid path if the code gets here - assert(m_device_support_directory.empty() == false); - if (m_device_support_directory[0]) - return m_device_support_directory.c_str(); - return NULL; -} - -const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion() { - if (m_sdk_sysroot) - return m_sdk_sysroot.GetCString(); - - if (m_device_support_directory_for_os_version.empty()) { - const PlatformRemoteDarwinDevice::SDKDirectoryInfo *sdk_dir_info = - GetSDKDirectoryForCurrentOSVersion(); - if (sdk_dir_info == NULL) - sdk_dir_info = GetSDKDirectoryForLatestOSVersion(); - if (sdk_dir_info) { - char path[PATH_MAX]; - if (sdk_dir_info->directory.GetPath(path, sizeof(path))) { - m_device_support_directory_for_os_version = path; - return m_device_support_directory_for_os_version.c_str(); - } - } else { - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_device_support_directory_for_os_version.assign(1, '\0'); - } - } - // We should have put a single NULL character into - // m_device_support_directory_for_os_version or it should have a valid path - // if the code gets here - assert(m_device_support_directory_for_os_version.empty() == false); - if (m_device_support_directory_for_os_version[0]) - return m_device_support_directory_for_os_version.c_str(); - return NULL; -} - -uint32_t PlatformRemoteDarwinDevice::FindFileInAllSDKs(const char *platform_file_path, - FileSpecList &file_list) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (platform_file_path && platform_file_path[0] && - UpdateSDKDirectoryInfosIfNeeded()) { - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - lldb_private::FileSpec local_file; - // First try for an exact match of major, minor and update - for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { - LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file_path, - m_sdk_directory_infos[sdk_idx].directory); - if (GetFileInSDK(platform_file_path, sdk_idx, local_file)) { - file_list.Append(local_file); - } - } - } - return file_list.GetSize(); -} - -bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path, - uint32_t sdk_idx, - lldb_private::FileSpec &local_file) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (sdk_idx < m_sdk_directory_infos.size()) { - std::string sdkroot_path = - m_sdk_directory_infos[sdk_idx].directory.GetPath(); - local_file.Clear(); - - if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) { - // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between - // the - // SDK root directory and the file path. - - const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; - for (size_t i = 0; paths_to_try[i] != nullptr; i++) { - local_file.SetFile(sdkroot_path, FileSpec::Style::native); - if (paths_to_try[i][0] != '\0') - local_file.AppendPathComponent(paths_to_try[i]); - local_file.AppendPathComponent(platform_file_path); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) { - if (log) - log->Printf("Found a copy of %s in the SDK dir %s/%s", - platform_file_path, sdkroot_path.c_str(), - paths_to_try[i]); - return true; - } - local_file.Clear(); - } - } - } - return false; -} - -Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - Status error; - char platform_file_path[PATH_MAX]; - if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { - char resolved_path[PATH_MAX]; - - const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); - if (os_version_dir) { - ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir, - platform_file_path); - - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) { - if (log) { - log->Printf("Found a copy of %s in the DeviceSupport dir %s", - platform_file_path, os_version_dir); - } - return error; - } - - ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s", - os_version_dir, platform_file_path); - - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) { - if (log) { - log->Printf( - "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", - platform_file_path, os_version_dir); - } - return error; - } - ::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s", - os_version_dir, platform_file_path); - - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) { - if (log) { - log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols", - platform_file_path, os_version_dir); - } - return error; - } - } - local_file = platform_file; - if (FileSystem::Instance().Exists(local_file)) - return error; - - error.SetErrorStringWithFormat( - "unable to locate a platform file for '%s' in platform '%s'", - platform_file_path, GetPluginName().GetCString()); - } else { - error.SetErrorString("invalid platform file argument"); - } - return error; -} - -Status PlatformRemoteDarwinDevice::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - // For iOS, the SDK files are all cached locally on the host system. So first - // we ask for the file in the cached SDK, then we attempt to get a shared - // module for the right architecture with the right UUID. - const FileSpec &platform_file = module_spec.GetFileSpec(); - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - - Status error; - char platform_file_path[PATH_MAX]; - - if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { - ModuleSpec platform_module_spec(module_spec); - - UpdateSDKDirectoryInfosIfNeeded(); - - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - - // If we are connected we migth be able to correctly deduce the SDK - // directory using the OS build. - const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); - if (connected_sdk_idx < num_sdk_infos) { - LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, - m_sdk_directory_infos[connected_sdk_idx].directory); - if (GetFileInSDK(platform_file_path, connected_sdk_idx, - platform_module_spec.GetFileSpec())) { - module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); - if (module_sp) { - m_last_module_sdk_idx = connected_sdk_idx; - error.Clear(); - return error; - } - } - } - - // Try the last SDK index if it is set as most files from an SDK will tend - // to be valid in that same SDK. - if (m_last_module_sdk_idx < num_sdk_infos) { - LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, - m_sdk_directory_infos[m_last_module_sdk_idx].directory); - if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, - platform_module_spec.GetFileSpec())) { - module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); - if (module_sp) { - error.Clear(); - return error; - } - } - } - - // First try for an exact match of major, minor and update: If a particalar - // SDK version was specified via --version or --build, look for a match on - // disk. - const SDKDirectoryInfo *current_sdk_info = - GetSDKDirectoryForCurrentOSVersion(); - const uint32_t current_sdk_idx = - GetSDKIndexBySDKDirectoryInfo(current_sdk_info); - if (current_sdk_idx < num_sdk_infos && - current_sdk_idx != m_last_module_sdk_idx) { - LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, - m_sdk_directory_infos[current_sdk_idx].directory); - if (GetFileInSDK(platform_file_path, current_sdk_idx, - platform_module_spec.GetFileSpec())) { - module_sp.reset(); - error = ResolveExecutable(platform_module_spec, module_sp, NULL); - if (module_sp) { - m_last_module_sdk_idx = current_sdk_idx; - error.Clear(); - return error; - } - } - } - - // Second try all SDKs that were found. - for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { - if (m_last_module_sdk_idx == sdk_idx) { - // Skip the last module SDK index if we already searched it above - continue; - } - LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, - m_sdk_directory_infos[sdk_idx].directory); - if (GetFileInSDK(platform_file_path, sdk_idx, - platform_module_spec.GetFileSpec())) { - // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); - - error = ResolveExecutable(platform_module_spec, module_sp, NULL); - if (module_sp) { - // Remember the index of the last SDK that we found a file in in case - // the wrong SDK was selected. - m_last_module_sdk_idx = sdk_idx; - error.Clear(); - return error; - } - } - } - } - // Not the module we are looking for... Nothing to see here... - module_sp.reset(); - - // This may not be an SDK-related module. Try whether we can bring in the - // thing to our local cache. - error = GetSharedModuleWithLocalCache(module_spec, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - if (error.Success()) - return error; - - // See if the file is present in any of the module_search_paths_ptr - // directories. - if (!module_sp) - error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, - module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); - - if (error.Success()) - return error; - - const bool always_create = false; - error = ModuleList::GetSharedModule( - module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr, always_create); - - if (module_sp) - module_sp->SetPlatformFileSpec(platform_file); - - return error; -} - -uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() { - if (IsConnected()) { - if (m_connected_module_sdk_idx == UINT32_MAX) { - std::string build; - if (GetRemoteOSBuildString(build)) { - const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); - for (uint32_t i = 0; i < num_sdk_infos; ++i) { - const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; - if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), - build.c_str())) { - m_connected_module_sdk_idx = i; - } - } - } - } - } else { - m_connected_module_sdk_idx = UINT32_MAX; - } - return m_connected_module_sdk_idx; -} - -uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo( - const SDKDirectoryInfo *sdk_info) { - if (sdk_info == NULL) { - return UINT32_MAX; - } - - return sdk_info - &m_sdk_directory_infos[0]; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h deleted file mode 100644 index d32179d6c98e3..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h +++ /dev/null @@ -1,112 +0,0 @@ -//===-- PlatformRemoteDarwinDevice.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformRemoteDarwinDevice_h_ -#define liblldb_PlatformRemoteDarwinDevice_h_ - -#include <string> - -#include "PlatformDarwin.h" -#include "lldb/Utility/FileSpec.h" - -#include "llvm/Support/FileSystem.h" - -class PlatformRemoteDarwinDevice : public PlatformDarwin { -public: - PlatformRemoteDarwinDevice(); - - ~PlatformRemoteDarwinDevice() override; - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - lldb_private::Status ResolveExecutable( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr) override; - - void GetStatus(lldb_private::Stream &strm) override; - - virtual lldb_private::Status - GetSymbolFile(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file); - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - void - AddClangModuleCompilationOptions(lldb_private::Target *target, - std::vector<std::string> &options) override { - return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneOS); - } - -protected: - struct SDKDirectoryInfo { - SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec); - lldb_private::FileSpec directory; - lldb_private::ConstString build; - llvm::VersionTuple version; - bool user_cached; - }; - - typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection; - - std::mutex m_sdk_dir_mutex; - SDKDirectoryInfoCollection m_sdk_directory_infos; - std::string m_device_support_directory; - std::string m_device_support_directory_for_os_version; - std::string m_build_update; - uint32_t m_last_module_sdk_idx; - uint32_t m_connected_module_sdk_idx; - - bool UpdateSDKDirectoryInfosIfNeeded(); - - const char *GetDeviceSupportDirectory(); - - const char *GetDeviceSupportDirectoryForOSVersion(); - - const SDKDirectoryInfo *GetSDKDirectoryForLatestOSVersion(); - - const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion(); - - static lldb_private::FileSystem::EnumerateDirectoryResult - GetContainedFilesIntoVectorOfStringsCallback(void *baton, - llvm::sys::fs::file_type ft, - llvm::StringRef path); - - uint32_t FindFileInAllSDKs(const char *platform_file_path, - lldb_private::FileSpecList &file_list); - - bool GetFileInSDK(const char *platform_file_path, uint32_t sdk_idx, - lldb_private::FileSpec &local_file); - - uint32_t FindFileInAllSDKs(const lldb_private::FileSpec &platform_file, - lldb_private::FileSpecList &file_list); - - uint32_t GetConnectedSDKIndex(); - - // Get index of SDK in SDKDirectoryInfoCollection by its pointer and return - // UINT32_MAX if that SDK not found. - uint32_t GetSDKIndexBySDKDirectoryInfo(const SDKDirectoryInfo *sdk_info); - - - virtual void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) = 0; - - virtual std::string GetPlatformName () = 0; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformRemoteDarwinDevice); -}; - -#endif // liblldb_PlatformRemoteDarwinDevice_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp deleted file mode 100644 index b69d7ea36abf3..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ /dev/null @@ -1,161 +0,0 @@ -//===-- PlatformRemoteiOS.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformRemoteiOS.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformRemoteiOS::Initialize() { - PlatformDarwin::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin(PlatformRemoteiOS::GetPluginNameStatic(), - PlatformRemoteiOS::GetDescriptionStatic(), - PlatformRemoteiOS::CreateInstance); - } -} - -void PlatformRemoteiOS::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformRemoteiOS::CreateInstance); - } - } - - PlatformDarwin::Terminate(); -} - -PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformRemoteiOS::%s(force=%s, arch={%s,%s})", __FUNCTION__, - force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::arm: - case llvm::Triple::aarch64: - case llvm::Triple::thumb: { - const llvm::Triple &triple = arch->GetTriple(); - llvm::Triple::VendorType vendor = triple.getVendor(); - switch (vendor) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - -#endif - default: - break; - } - if (create) { - switch (triple.getOS()) { - case llvm::Triple::Darwin: // Deprecated, but still support Darwin for - // historical reasons - case llvm::Triple::IOS: // This is the right triple value for iOS - // debugging - break; - - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - - if (create) { - if (log) - log->Printf("PlatformRemoteiOS::%s() creating platform", __FUNCTION__); - - return lldb::PlatformSP(new PlatformRemoteiOS()); - } - - if (log) - log->Printf("PlatformRemoteiOS::%s() aborting creation of platform", - __FUNCTION__); - - return lldb::PlatformSP(); -} - -lldb_private::ConstString PlatformRemoteiOS::GetPluginNameStatic() { - static ConstString g_name("remote-ios"); - return g_name; -} - -const char *PlatformRemoteiOS::GetDescriptionStatic() { - return "Remote iOS platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformRemoteiOS::PlatformRemoteiOS() - : PlatformRemoteDarwinDevice() {} - -bool PlatformRemoteiOS::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - return ARMGetSupportedArchitectureAtIndex(idx, arch); -} - - -void PlatformRemoteiOS::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) -{ - dirnames.clear(); - dirnames.push_back("iOS DeviceSupport"); -} - -std::string PlatformRemoteiOS::GetPlatformName () -{ - return "iPhoneOS.platform"; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h deleted file mode 100644 index 7e45dc3c2889b..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h +++ /dev/null @@ -1,72 +0,0 @@ -//===-- PlatformRemoteiOS.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformRemoteiOS_h_ -#define liblldb_PlatformRemoteiOS_h_ - -#include <string> - -#include "PlatformRemoteDarwinDevice.h" -#include "lldb/Utility/FileSpec.h" - -#include "llvm/Support/FileSystem.h" - -class PlatformRemoteiOS : public PlatformRemoteDarwinDevice { -public: - PlatformRemoteiOS(); - - ~PlatformRemoteiOS() override = default; - - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - const char *GetDescription() override { return GetDescriptionStatic(); } - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - -protected: - - //------------------------------------------------------------ - // lldb_private::PlatformRemoteDarwinDevice functions - //------------------------------------------------------------ - - void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override; - - std::string GetPlatformName () override; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformRemoteiOS); -}; - -#endif // liblldb_PlatformRemoteiOS_h_ diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp deleted file mode 100644 index b1d5960bb6823..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp +++ /dev/null @@ -1,423 +0,0 @@ -//===-- PlatformiOSSimulator.cpp -----------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformiOSSimulator.h" - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleList.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" - -#include "llvm/Support/FileSystem.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------ -// Static Variables -//------------------------------------------------------------------ -static uint32_t g_initialize_count = 0; - -//------------------------------------------------------------------ -// Static Functions -//------------------------------------------------------------------ -void PlatformiOSSimulator::Initialize() { - PlatformAppleSimulator::Initialize(); - - if (g_initialize_count++ == 0) { - PluginManager::RegisterPlugin(PlatformiOSSimulator::GetPluginNameStatic(), - PlatformiOSSimulator::GetDescriptionStatic(), - PlatformiOSSimulator::CreateInstance); - } -} - -void PlatformiOSSimulator::Terminate() { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { - PluginManager::UnregisterPlugin(PlatformiOSSimulator::CreateInstance); - } - } - - PlatformAppleSimulator::Terminate(); -} - -PlatformSP PlatformiOSSimulator::CreateInstance(bool force, - const ArchSpec *arch) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) { - const char *arch_name; - if (arch && arch->GetArchitectureName()) - arch_name = arch->GetArchitectureName(); - else - arch_name = "<null>"; - - const char *triple_cstr = - arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - - log->Printf("PlatformiOSSimulator::%s(force=%s, arch={%s,%s})", - __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } - - bool create = force; - if (!create && arch && arch->IsValid()) { - switch (arch->GetMachine()) { - case llvm::Triple::x86_64: - case llvm::Triple::x86: { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::Apple: - create = true; - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the vendor if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; -#endif - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::Darwin: // Deprecated, but still support Darwin for - // historical reasons - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: // IOS is not used for simulator triples, but - // accept it just in case - break; - -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and it - // "unknown" wasn't specified (it was just returned because it was NOT - // specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif - default: - create = false; - break; - } - } - } break; - default: - break; - } - } - if (create) { - if (log) - log->Printf("PlatformiOSSimulator::%s() creating platform", __FUNCTION__); - - return PlatformSP(new PlatformiOSSimulator()); - } - - if (log) - log->Printf("PlatformiOSSimulator::%s() aborting creation of platform", - __FUNCTION__); - - return PlatformSP(); -} - -lldb_private::ConstString PlatformiOSSimulator::GetPluginNameStatic() { - static ConstString g_name("ios-simulator"); - return g_name; -} - -const char *PlatformiOSSimulator::GetDescriptionStatic() { - return "iOS simulator platform plug-in."; -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformiOSSimulator::PlatformiOSSimulator() - : PlatformAppleSimulator(), m_sdk_dir_mutex(), m_sdk_directory(), - m_build_update() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformiOSSimulator::~PlatformiOSSimulator() {} - -void PlatformiOSSimulator::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - const char *sdk_directory = GetSDKDirectoryAsCString(); - if (sdk_directory) - strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); - else - strm.PutCString(" SDK Path: error: unable to locate SDK\n"); - PlatformAppleSimulator::GetStatus(strm); -} - -Status PlatformiOSSimulator::ResolveExecutable( - const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Status error; - // Nothing special to do here, just use the actual file and architecture - - ModuleSpec resolved_module_spec(module_spec); - - // If we have "ls" as the exe_file, resolve the executable loation based on - // the current path variables - // TODO: resolve bare executables in the Platform SDK - // if (!resolved_exe_file.Exists()) - // resolved_exe_file.ResolveExecutableLocation (); - - // Resolve any executable within a bundle on MacOSX - // TODO: verify that this handles shallow bundles, if not then implement one - // ourselves - Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); - - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { - if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - - if (exe_module_sp && exe_module_sp->GetObjectFile()) - return error; - exe_module_sp.reset(); - } - // No valid architecture was specified or the exact ARM slice wasn't found - // so ask the platform for the architectures that we should be using (in - // the correct order) and see if we can find a match that way - StreamString arch_names; - ArchSpec platform_arch; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - // Only match x86 with x86 and x86_64 with x86_64... - if (!module_spec.GetArchitecture().IsValid() || - module_spec.GetArchitecture().GetCore() == - resolved_module_spec.GetArchitecture().GetCore()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - NULL, NULL, NULL); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString(platform_arch.GetArchitectureName()); - } - } - - if (error.Fail() || !exe_module_sp) { - if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetString().str().c_str()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } else { - error.SetErrorStringWithFormat("'%s' does not exist", - module_spec.GetFileSpec().GetPath().c_str()); - } - - return error; -} - -static FileSystem::EnumerateDirectoryResult -EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft, - llvm::StringRef path) { - if (ft == llvm::sys::fs::file_type::directory_file) { - FileSpec file_spec(path); - const char *filename = file_spec.GetFilename().GetCString(); - if (filename && - strncmp(filename, "iPhoneSimulator", strlen("iPhoneSimulator")) == 0) { - ::snprintf((char *)baton, PATH_MAX, "%s", filename); - return FileSystem::eEnumerateDirectoryResultQuit; - } - } - return FileSystem::eEnumerateDirectoryResultNext; -} - -const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() { - std::lock_guard<std::mutex> guard(m_sdk_dir_mutex); - if (m_sdk_directory.empty()) { - const char *developer_dir = GetDeveloperDirectory(); - if (developer_dir) { - char sdks_directory[PATH_MAX]; - char sdk_dirname[PATH_MAX]; - sdk_dirname[0] = '\0'; - snprintf(sdks_directory, sizeof(sdks_directory), - "%s/Platforms/iPhoneSimulator.platform/Developer/SDKs", - developer_dir); - FileSpec simulator_sdk_spec; - bool find_directories = true; - bool find_files = false; - bool find_other = false; - FileSystem::Instance().EnumerateDirectory( - sdks_directory, find_directories, find_files, find_other, - EnumerateDirectoryCallback, sdk_dirname); - - if (sdk_dirname[0]) { - m_sdk_directory = sdks_directory; - m_sdk_directory.append(1, '/'); - m_sdk_directory.append(sdk_dirname); - return m_sdk_directory.c_str(); - } - } - // Assign a single NULL character so we know we tried to find the device - // support directory and we don't keep trying to find it over and over. - m_sdk_directory.assign(1, '\0'); - } - - // We should have put a single NULL character into m_sdk_directory or it - // should have a valid path if the code gets here - assert(m_sdk_directory.empty() == false); - if (m_sdk_directory[0]) - return m_sdk_directory.c_str(); - return NULL; -} - -Status PlatformiOSSimulator::GetSymbolFile(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - Status error; - char platform_file_path[PATH_MAX]; - if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { - char resolved_path[PATH_MAX]; - - const char *sdk_dir = GetSDKDirectoryAsCString(); - if (sdk_dir) { - ::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", sdk_dir, - platform_file_path); - - // First try in the SDK and see if the file is in there - local_file.SetFile(resolved_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - - // Else fall back to the actual path itself - local_file.SetFile(platform_file_path, FileSpec::Style::native); - FileSystem::Instance().Resolve(local_file); - if (FileSystem::Instance().Exists(local_file)) - return error; - } - error.SetErrorStringWithFormat( - "unable to locate a platform file for '%s' in platform '%s'", - platform_file_path, GetPluginName().GetCString()); - } else { - error.SetErrorString("invalid platform file argument"); - } - return error; -} - -Status PlatformiOSSimulator::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - // For iOS, the SDK files are all cached locally on the host system. So first - // we ask for the file in the cached SDK, then we attempt to get a shared - // module for the right architecture with the right UUID. - Status error; - ModuleSpec platform_module_spec(module_spec); - const FileSpec &platform_file = module_spec.GetFileSpec(); - error = GetSymbolFile(platform_file, module_spec.GetUUIDPtr(), - platform_module_spec.GetFileSpec()); - if (error.Success()) { - error = ResolveExecutable(platform_module_spec, module_sp, - module_search_paths_ptr); - } else { - const bool always_create = false; - error = ModuleList::GetSharedModule( - module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, - did_create_ptr, always_create); - } - if (module_sp) - module_sp->SetPlatformFileSpec(platform_file); - - return error; -} - -uint32_t -PlatformiOSSimulator::FindProcesses(const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) { - ProcessInstanceInfoList all_osx_process_infos; - // First we get all OSX processes - const uint32_t n = Host::FindProcesses(match_info, all_osx_process_infos); - - // Now we filter them down to only the iOS triples - for (uint32_t i = 0; i < n; ++i) { - const ProcessInstanceInfo &proc_info = - all_osx_process_infos.GetProcessInfoAtIndex(i); - if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::IOS) { - process_infos.Append(proc_info); - } - } - return process_infos.GetSize(); -} - -bool PlatformiOSSimulator::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - static const ArchSpec platform_arch( - HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); - static const ArchSpec platform_arch64( - HostInfo::GetArchitecture(HostInfo::eArchKind64)); - - if (idx == 0) { - arch = platform_arch; - if (arch.IsValid()) { - arch.GetTriple().setOS(llvm::Triple::IOS); - return true; - } - } else { - if (platform_arch.IsExactMatch(platform_arch64)) { - // This macosx platform supports both 32 and 64 bit. - if (idx == 1) { - // 32/64: return "x86_64-apple-macosx" for architecture 1 - arch = platform_arch64; - return true; - } else if (idx == 2 || idx == 3) { - arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); - if (arch.IsValid()) { - if (idx == 2) - arch.GetTriple().setOS(llvm::Triple::IOS); - // 32/64: return "i386-apple-ios" for architecture 2 32/64: return - // "i386-apple-macosx" for architecture 3 - return true; - } - } - } else if (idx == 1) { - // This macosx platform supports only 32 bit, so return the *-apple- - // macosx version - arch = platform_arch; - return true; - } - } - return false; -} diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h deleted file mode 100644 index 4ac43a4dde28d..0000000000000 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- PlatformiOSSimulator.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformiOSSimulator_h_ -#define liblldb_PlatformiOSSimulator_h_ - -#include <mutex> -#include <string> - -#include "PlatformAppleSimulator.h" - -class PlatformiOSSimulator : public PlatformAppleSimulator { -public: - PlatformiOSSimulator(); - - ~PlatformiOSSimulator() override; - - //------------------------------------------------------------ - // Class Functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetDescriptionStatic(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override { - return GetPluginNameStatic(); - } - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - lldb_private::Status ResolveExecutable( - const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr) override; - - const char *GetDescription() override { return GetDescriptionStatic(); } - - void GetStatus(lldb_private::Stream &strm) override; - - virtual lldb_private::Status - GetSymbolFile(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid_ptr, - lldb_private::FileSpec &local_file); - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - uint32_t - FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, - lldb_private::ProcessInstanceInfoList &process_infos) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - void - AddClangModuleCompilationOptions(lldb_private::Target *target, - std::vector<std::string> &options) override { - return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType( - target, options, PlatformDarwin::SDKType::iPhoneSimulator); - } - -protected: - std::mutex m_sdk_dir_mutex; - std::string m_sdk_directory; - std::string m_build_update; - - const char *GetSDKDirectoryAsCString(); - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformiOSSimulator); -}; - -#endif // liblldb_PlatformiOSSimulator_h_ diff --git a/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt b/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt deleted file mode 100644 index 946ff0a64c26f..0000000000000 --- a/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -remove_module_flags() -include_directories(.) - -add_lldb_library(lldbPluginPlatformMacOSXObjCXX - PlatformiOSSimulatorCoreSimulatorSupport.mm - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - lldbUtility - ${EXTRA_LIBS} - - LINK_COMPONENTS - Object - Support - ) diff --git a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h deleted file mode 100644 index bec35aaaf33b6..0000000000000 --- a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h +++ /dev/null @@ -1,221 +0,0 @@ -//===-- PlatformiOSSimulatorCoreSimulatorSupport.h ----------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ -#define liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ - -#include <functional> -#include <ostream> -#include <string> -#include <vector> -#ifdef __APPLE__ -#include <objc/objc.h> -#else -typedef void *id; -#endif -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/Args.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Status.h" - -#include "llvm/ADT/Optional.h" - -// And now the actual magic -namespace CoreSimulatorSupport { -class Process { -public: - lldb::pid_t GetPID() { return m_pid; } - - explicit operator bool() { return m_pid != LLDB_INVALID_PROCESS_ID; } - - lldb_private::Status GetError() { return m_error; } - -private: - Process(lldb::pid_t p); - - Process(lldb_private::Status error); - - Process(lldb::pid_t p, lldb_private::Status error); - - lldb::pid_t m_pid; - lldb_private::Status m_error; - - friend class Device; -}; - -class ModelIdentifier { -public: - ModelIdentifier(const std::string &mi); - ModelIdentifier(); - - explicit operator bool() const { return !m_versions.empty(); } - - size_t GetNumVersions() const { return m_versions.size(); } - - unsigned int GetVersionAtIndex(size_t idx) const { return m_versions[idx]; } - - std::string GetFamily() const { return m_family.c_str(); } - -private: - std::string m_family; - std::vector<unsigned int> m_versions; -}; - -class DeviceType { -public: - enum class ProductFamilyID : int32_t { - iPhone = 1, - iPad = 2, - appleTV = 3, - appleWatch = 4 - }; - - DeviceType(); - - DeviceType(id d); - - explicit operator bool(); - - std::string GetName(); - - lldb_private::ConstString GetIdentifier(); - - ModelIdentifier GetModelIdentifier(); - - lldb_private::ConstString GetProductFamily(); - - ProductFamilyID GetProductFamilyID(); - -private: - id m_dev; - llvm::Optional<ModelIdentifier> m_model_identifier; -}; - -class OSVersion { -public: - OSVersion(const std::string &ver, const std::string &build); - - OSVersion(); - - explicit operator bool() const { return !m_versions.empty(); } - - size_t GetNumVersions() const { return m_versions.size(); } - - unsigned int GetVersionAtIndex(size_t idx) const { return m_versions[idx]; } - - const char *GetBuild() const { return m_build.c_str(); } - -private: - std::vector<unsigned int> m_versions; - std::string m_build; -}; - -class DeviceRuntime { -public: - DeviceRuntime(); - - DeviceRuntime(id d); - - explicit operator bool(); - - OSVersion GetVersion(); - - bool IsAvailable(); - -private: - id m_dev; - llvm::Optional<OSVersion> m_os_version; -}; - -class Device { -private: - typedef unsigned long int NSUInteger; - -public: - enum class State : NSUInteger { - Creating, - Shutdown, - Booting, - Booted, - ShuttingDown - }; - - Device(); - - Device(id d); - - explicit operator bool(); - - std::string GetName() const; - - DeviceType GetDeviceType(); - - DeviceRuntime GetDeviceRuntime(); - - State GetState(); - - bool Boot(lldb_private::Status &err); - - bool Shutdown(lldb_private::Status &err); - - std::string GetUDID() const; - - Process Spawn(lldb_private::ProcessLaunchInfo &launch_info); - -private: - id m_dev; - llvm::Optional<DeviceType> m_dev_type; - llvm::Optional<DeviceRuntime> m_dev_runtime; - - friend class DeviceSet; -}; - -bool operator>(const OSVersion &lhs, const OSVersion &rhs); - -bool operator>(const ModelIdentifier &lhs, const ModelIdentifier &rhs); - -bool operator<(const OSVersion &lhs, const OSVersion &rhs); - -bool operator<(const ModelIdentifier &lhs, const ModelIdentifier &rhs); - -bool operator==(const OSVersion &lhs, const OSVersion &rhs); - -bool operator==(const ModelIdentifier &lhs, const ModelIdentifier &rhs); - -bool operator!=(const OSVersion &lhs, const OSVersion &rhs); - -bool operator!=(const ModelIdentifier &lhs, const ModelIdentifier &rhs); - -class DeviceSet { -public: - static DeviceSet GetAllDevices(const char *developer_dir); - - static DeviceSet GetAvailableDevices(const char *developer_dir); - - size_t GetNumDevices(); - - Device GetDeviceAtIndex(size_t idx); - - void ForEach(std::function<bool(const Device &)> f); - - DeviceSet GetDevicesIf(std::function<bool(Device)> f); - - DeviceSet GetDevices(DeviceType::ProductFamilyID dev_id); - - Device GetFanciest(DeviceType::ProductFamilyID dev_id); - -private: - DeviceSet(id arr) : m_dev(arr) {} - - id m_dev; -}; -} - -#endif // liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_ diff --git a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm deleted file mode 100644 index a601e27dc8a11..0000000000000 --- a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm +++ /dev/null @@ -1,634 +0,0 @@ -//===-- PlatformiOSSimulatorCoreSimulatorSupport.cpp ---------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformiOSSimulatorCoreSimulatorSupport.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include <CoreFoundation/CoreFoundation.h> -#include <Foundation/Foundation.h> -// Project includes -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Target/FileAction.h" - -#include "llvm/ADT/StringRef.h" - -using namespace lldb_private; -// CoreSimulator lives as part of Xcode, which means we can't really link -// against it, so we dlopen() -// it at runtime, and error out nicely if that fails -@interface SimServiceContext { -} -+ (id)sharedServiceContextForDeveloperDir:(NSString *)dir - error:(NSError **)error; -@end -// However, the drawback is that the compiler will not know about the selectors -// we're trying to use -// until runtime; to appease clang in this regard, define a fake protocol on -// NSObject that exposes -// the needed interface names for us -@protocol LLDBCoreSimulatorSupport <NSObject> -- (id)defaultDeviceSetWithError:(NSError **)error; -- (NSArray *)devices; -- (id)deviceType; -- (NSString *)name; -- (NSString *)identifier; -- (NSString *)modelIdentifier; -- (NSString *)productFamily; -- (int32_t)productFamilyID; -- (id)runtime; -- (BOOL)available; -- (NSString *)versionString; -- (NSString *)buildVersionString; -- (BOOL)bootWithOptions:(NSDictionary *)options error:(NSError **)error; -- (NSUInteger)state; -- (BOOL)shutdownWithError:(NSError **)error; -- (NSUUID *)UDID; -- (pid_t)spawnWithPath:(NSString *)path - options:(NSDictionary *)options - terminationHandler:(void (^)(int status))terminationHandler - error:(NSError **)error; -@end - -CoreSimulatorSupport::Process::Process(lldb::pid_t p) : m_pid(p), m_error() {} - -CoreSimulatorSupport::Process::Process(Status error) - : m_pid(LLDB_INVALID_PROCESS_ID), m_error(error) {} - -CoreSimulatorSupport::Process::Process(lldb::pid_t p, Status error) - : m_pid(p), m_error(error) {} - -CoreSimulatorSupport::DeviceType::DeviceType() - : m_dev(nil), m_model_identifier() {} - -CoreSimulatorSupport::DeviceType::DeviceType(id d) - : m_dev(d), m_model_identifier() {} - -CoreSimulatorSupport::DeviceType::operator bool() { return m_dev != nil; } - -ConstString CoreSimulatorSupport::DeviceType::GetIdentifier() { - return ConstString([[m_dev identifier] UTF8String]); -} - -ConstString CoreSimulatorSupport::DeviceType::GetProductFamily() { - return ConstString([[m_dev productFamily] UTF8String]); -} - -CoreSimulatorSupport::DeviceType::ProductFamilyID -CoreSimulatorSupport::DeviceType::GetProductFamilyID() { - return ProductFamilyID([m_dev productFamilyID]); -} - -CoreSimulatorSupport::DeviceRuntime::DeviceRuntime() - : m_dev(nil), m_os_version() {} - -CoreSimulatorSupport::DeviceRuntime::DeviceRuntime(id d) - : m_dev(d), m_os_version() {} - -CoreSimulatorSupport::DeviceRuntime::operator bool() { return m_dev != nil; } - -bool CoreSimulatorSupport::DeviceRuntime::IsAvailable() { - return [m_dev available]; -} - -CoreSimulatorSupport::Device::Device() - : m_dev(nil), m_dev_type(), m_dev_runtime() {} - -CoreSimulatorSupport::Device::Device(id d) - : m_dev(d), m_dev_type(), m_dev_runtime() {} - -CoreSimulatorSupport::Device::operator bool() { return m_dev != nil; } - -CoreSimulatorSupport::Device::State CoreSimulatorSupport::Device::GetState() { - return (State)([m_dev state]); -} - -CoreSimulatorSupport::ModelIdentifier::ModelIdentifier(const std::string &mi) - : m_family(), m_versions() { - bool any = false; - bool first_digit = false; - unsigned int val = 0; - - for (char c : mi) { - any = true; - if (::isdigit(c)) { - if (!first_digit) - first_digit = true; - val = 10 * val + (c - '0'); - } else if (c == ',') { - if (first_digit) { - m_versions.push_back(val); - val = 0; - } else - m_family.push_back(c); - } else { - if (first_digit) { - m_family.clear(); - m_versions.clear(); - return; - } else { - m_family.push_back(c); - } - } - } - - if (first_digit) - m_versions.push_back(val); -} - -CoreSimulatorSupport::ModelIdentifier::ModelIdentifier() - : ModelIdentifier("") {} - -CoreSimulatorSupport::OSVersion::OSVersion(const std::string &ver, - const std::string &build) - : m_versions(), m_build(build) { - bool any = false; - unsigned int val = 0; - for (char c : ver) { - if (c == '.') { - m_versions.push_back(val); - val = 0; - } else if (::isdigit(c)) { - val = 10 * val + (c - '0'); - any = true; - } else { - m_versions.clear(); - return; - } - } - if (any) - m_versions.push_back(val); -} - -CoreSimulatorSupport::OSVersion::OSVersion() : OSVersion("", "") {} - -CoreSimulatorSupport::ModelIdentifier -CoreSimulatorSupport::DeviceType::GetModelIdentifier() { - if (!m_model_identifier.hasValue()) { - auto utf8_model_id = [[m_dev modelIdentifier] UTF8String]; - if (utf8_model_id && *utf8_model_id) - m_model_identifier = ModelIdentifier(utf8_model_id); - } - - if (m_model_identifier.hasValue()) - return m_model_identifier.getValue(); - else - return ModelIdentifier(); -} - -CoreSimulatorSupport::OSVersion -CoreSimulatorSupport::DeviceRuntime::GetVersion() { - if (!m_os_version.hasValue()) { - auto utf8_ver_string = [[m_dev versionString] UTF8String]; - auto utf8_build_ver = [[m_dev buildVersionString] UTF8String]; - if (utf8_ver_string && *utf8_ver_string && utf8_build_ver && - *utf8_build_ver) { - m_os_version = OSVersion(utf8_ver_string, utf8_build_ver); - } - } - - if (m_os_version.hasValue()) - return m_os_version.getValue(); - return OSVersion(); -} - -std::string CoreSimulatorSupport::DeviceType::GetName() { - auto utf8_name = [[m_dev name] UTF8String]; - if (utf8_name) - return std::string(utf8_name); - return ""; -} - -std::string CoreSimulatorSupport::Device::GetName() const { - auto utf8_name = [[m_dev name] UTF8String]; - if (utf8_name) - return std::string(utf8_name); - return ""; -} - -std::string CoreSimulatorSupport::Device::GetUDID() const { - auto utf8_udid = [[[m_dev UDID] UUIDString] UTF8String]; - if (utf8_udid) - return std::string(utf8_udid); - else - return std::string(); -} - -CoreSimulatorSupport::DeviceType CoreSimulatorSupport::Device::GetDeviceType() { - if (!m_dev_type.hasValue()) - m_dev_type = DeviceType([m_dev deviceType]); - - return m_dev_type.getValue(); -} - -CoreSimulatorSupport::DeviceRuntime -CoreSimulatorSupport::Device::GetDeviceRuntime() { - if (!m_dev_runtime.hasValue()) - m_dev_runtime = DeviceRuntime([m_dev runtime]); - - return m_dev_runtime.getValue(); -} - -bool CoreSimulatorSupport:: -operator>(const CoreSimulatorSupport::OSVersion &lhs, - const CoreSimulatorSupport::OSVersion &rhs) { - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l > r) - return true; - } - return false; -} - -bool CoreSimulatorSupport:: -operator>(const CoreSimulatorSupport::ModelIdentifier &lhs, - const CoreSimulatorSupport::ModelIdentifier &rhs) { - if (lhs.GetFamily() != rhs.GetFamily()) - return false; - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l > r) - return true; - } - return false; -} - -bool CoreSimulatorSupport:: -operator<(const CoreSimulatorSupport::OSVersion &lhs, - const CoreSimulatorSupport::OSVersion &rhs) { - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l < r) - return true; - } - return false; -} - -bool CoreSimulatorSupport:: -operator<(const CoreSimulatorSupport::ModelIdentifier &lhs, - const CoreSimulatorSupport::ModelIdentifier &rhs) { - if (lhs.GetFamily() != rhs.GetFamily()) - return false; - - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l < r) - return true; - } - return false; -} - -bool CoreSimulatorSupport:: -operator==(const CoreSimulatorSupport::OSVersion &lhs, - const CoreSimulatorSupport::OSVersion &rhs) { - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l != r) - return false; - } - return true; -} - -bool CoreSimulatorSupport:: -operator==(const CoreSimulatorSupport::ModelIdentifier &lhs, - const CoreSimulatorSupport::ModelIdentifier &rhs) { - if (lhs.GetFamily() != rhs.GetFamily()) - return false; - - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l != r) - return false; - } - return true; -} - -bool CoreSimulatorSupport:: -operator!=(const CoreSimulatorSupport::OSVersion &lhs, - const CoreSimulatorSupport::OSVersion &rhs) { - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l != r) - return true; - } - return false; -} - -bool CoreSimulatorSupport:: -operator!=(const CoreSimulatorSupport::ModelIdentifier &lhs, - const CoreSimulatorSupport::ModelIdentifier &rhs) { - if (lhs.GetFamily() != rhs.GetFamily()) - return false; - - for (size_t i = 0; i < rhs.GetNumVersions(); i++) { - unsigned int l = lhs.GetVersionAtIndex(i); - unsigned int r = rhs.GetVersionAtIndex(i); - if (l != r) - return true; - } - return false; -} - -bool CoreSimulatorSupport::Device::Boot(Status &err) { - if (m_dev == nil) { - err.SetErrorString("no valid simulator instance"); - return false; - } - -#define kSimDeviceBootPersist \ - @"persist" /* An NSNumber (boolean) indicating whether or not the session \ - should outlive the calling process (default false) */ - - NSDictionary *options = @{ - kSimDeviceBootPersist : @NO, - }; - -#undef kSimDeviceBootPersist - - NSError *nserror; - if ([m_dev bootWithOptions:options error:&nserror]) { - err.Clear(); - return true; - } else { - err.SetErrorString([[nserror description] UTF8String]); - return false; - } -} - -bool CoreSimulatorSupport::Device::Shutdown(Status &err) { - NSError *nserror; - if ([m_dev shutdownWithError:&nserror]) { - err.Clear(); - return true; - } else { - err.SetErrorString([[nserror description] UTF8String]); - return false; - } -} - -static Status HandleFileAction(ProcessLaunchInfo &launch_info, - NSMutableDictionary *options, NSString *key, - const int fd, File &file) { - Status error; - const FileAction *file_action = launch_info.GetFileActionForFD(fd); - if (file_action) { - switch (file_action->GetAction()) { - case FileAction::eFileActionNone: - break; - - case FileAction::eFileActionClose: - error.SetErrorStringWithFormat("close file action for %i not supported", - fd); - break; - - case FileAction::eFileActionDuplicate: - error.SetErrorStringWithFormat( - "duplication file action for %i not supported", fd); - break; - - case FileAction::eFileActionOpen: { - FileSpec file_spec = file_action->GetFileSpec(); - if (file_spec) { - const int master_fd = launch_info.GetPTY().GetMasterFileDescriptor(); - if (master_fd != PseudoTerminal::invalid_fd) { - // Check in case our file action open wants to open the slave - const char *slave_path = launch_info.GetPTY().GetSlaveName(NULL, 0); - if (slave_path) { - FileSpec slave_spec(slave_path); - if (file_spec == slave_spec) { - int slave_fd = launch_info.GetPTY().GetSlaveFileDescriptor(); - if (slave_fd == PseudoTerminal::invalid_fd) - slave_fd = launch_info.GetPTY().OpenSlave(O_RDWR, nullptr, 0); - if (slave_fd == PseudoTerminal::invalid_fd) { - error.SetErrorStringWithFormat("unable to open slave pty '%s'", - slave_path); - return error; // Failure - } - [options setValue:[NSNumber numberWithInteger:slave_fd] - forKey:key]; - return error; // Success - } - } - } - Status posix_error; - int created_fd = - open(file_spec.GetPath().c_str(), file_action->GetActionArgument(), - S_IRUSR | S_IWUSR); - if (created_fd >= 0) { - file.SetDescriptor(created_fd, true); - [options setValue:[NSNumber numberWithInteger:created_fd] forKey:key]; - return error; // Success - } else { - posix_error.SetErrorToErrno(); - error.SetErrorStringWithFormat("unable to open file '%s': %s", - file_spec.GetPath().c_str(), - posix_error.AsCString()); - } - } - } break; - } - } - return error; // Success, no file action, nothing to do -} - -CoreSimulatorSupport::Process -CoreSimulatorSupport::Device::Spawn(ProcessLaunchInfo &launch_info) { -#define kSimDeviceSpawnEnvironment \ - @"environment" /* An NSDictionary (NSStrings -> NSStrings) of environment \ - key/values */ -#define kSimDeviceSpawnStdin @"stdin" /* An NSNumber corresponding to a fd */ -#define kSimDeviceSpawnStdout @"stdout" /* An NSNumber corresponding to a fd \ - */ -#define kSimDeviceSpawnStderr @"stderr" /* An NSNumber corresponding to a fd \ - */ -#define kSimDeviceSpawnArguments \ - @"arguments" /* An NSArray of strings to use as the argv array. If not \ - provided, path will be argv[0] */ -#define kSimDeviceSpawnWaitForDebugger \ - @"wait_for_debugger" /* An NSNumber (bool) */ - - NSMutableDictionary *options = [[NSMutableDictionary alloc] init]; - - if (launch_info.GetFlags().Test(lldb::eLaunchFlagDebug)) - [options setObject:@YES forKey:kSimDeviceSpawnWaitForDebugger]; - - if (launch_info.GetArguments().GetArgumentCount()) { - const Args &args(launch_info.GetArguments()); - NSMutableArray *args_array = [[NSMutableArray alloc] init]; - for (size_t idx = 0; idx < args.GetArgumentCount(); idx++) - [args_array - addObject:[NSString - stringWithUTF8String:args.GetArgumentAtIndex(idx)]]; - - [options setObject:args_array forKey:kSimDeviceSpawnArguments]; - } - - NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init]; - - for (const auto &KV : launch_info.GetEnvironment()) { - NSString *key_ns = [NSString stringWithUTF8String:KV.first().str().c_str()]; - NSString *value_ns = [NSString stringWithUTF8String:KV.second.c_str()]; - - [env_dict setValue:value_ns forKey:key_ns]; - } - - [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment]; - - Status error; - File stdin_file; - File stdout_file; - File stderr_file; - error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdin, - STDIN_FILENO, stdin_file); - - if (error.Fail()) - return CoreSimulatorSupport::Process(error); - - error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdout, - STDOUT_FILENO, stdout_file); - - if (error.Fail()) - return CoreSimulatorSupport::Process(error); - - error = HandleFileAction(launch_info, options, kSimDeviceSpawnStderr, - STDERR_FILENO, stderr_file); - - if (error.Fail()) - return CoreSimulatorSupport::Process(error); - -#undef kSimDeviceSpawnEnvironment -#undef kSimDeviceSpawnStdin -#undef kSimDeviceSpawnStdout -#undef kSimDeviceSpawnStderr -#undef kSimDeviceSpawnWaitForDebugger -#undef kSimDeviceSpawnArguments - - NSError *nserror; - - pid_t pid = [m_dev - spawnWithPath:[NSString stringWithUTF8String:launch_info - .GetExecutableFile() - .GetPath() - .c_str()] - options:options - terminationHandler:nil - error:&nserror]; - - if (pid < 0) { - const char *nserror_string = [[nserror description] UTF8String]; - error.SetErrorString(nserror_string ? nserror_string : "unable to launch"); - } - - return CoreSimulatorSupport::Process(pid, error); -} - -CoreSimulatorSupport::DeviceSet -CoreSimulatorSupport::DeviceSet::GetAllDevices(const char *developer_dir) { - if (!developer_dir || !developer_dir[0]) - return DeviceSet([NSArray new]); - - Class SimServiceContextClass = NSClassFromString(@"SimServiceContext"); - NSString *dev_dir = @(developer_dir); - NSError *error = nil; - - id serviceContext = - [SimServiceContextClass sharedServiceContextForDeveloperDir:dev_dir - error:&error]; - if (!serviceContext) - return DeviceSet([NSArray new]); - - return DeviceSet([[serviceContext defaultDeviceSetWithError:&error] devices]); -} - -CoreSimulatorSupport::DeviceSet -CoreSimulatorSupport::DeviceSet::GetAvailableDevices( - const char *developer_dir) { - return GetAllDevices(developer_dir).GetDevicesIf([](Device d) -> bool { - return (d && d.GetDeviceType() && d.GetDeviceRuntime() && - d.GetDeviceRuntime().IsAvailable()); - }); -} - -size_t CoreSimulatorSupport::DeviceSet::GetNumDevices() { - return [m_dev count]; -} - -CoreSimulatorSupport::Device -CoreSimulatorSupport::DeviceSet::GetDeviceAtIndex(size_t idx) { - if (idx < GetNumDevices()) - return Device([m_dev objectAtIndex:idx]); - return Device(); -} - -CoreSimulatorSupport::DeviceSet CoreSimulatorSupport::DeviceSet::GetDevicesIf( - std::function<bool(CoreSimulatorSupport::Device)> f) { - NSMutableArray *array = [[NSMutableArray alloc] init]; - for (NSUInteger i = 0; i < GetNumDevices(); i++) { - Device d(GetDeviceAtIndex(i)); - if (f(d)) - [array addObject:(id)d.m_dev]; - } - - return DeviceSet(array); -} - -void CoreSimulatorSupport::DeviceSet::ForEach( - std::function<bool(const Device &)> f) { - const size_t n = GetNumDevices(); - for (NSUInteger i = 0; i < n; ++i) { - if (!f(GetDeviceAtIndex(i))) - break; - } -} - -CoreSimulatorSupport::DeviceSet CoreSimulatorSupport::DeviceSet::GetDevices( - CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id) { - NSMutableArray *array = [[NSMutableArray alloc] init]; - const size_t n = GetNumDevices(); - for (NSUInteger i = 0; i < n; ++i) { - Device d(GetDeviceAtIndex(i)); - if (d && d.GetDeviceType() && - d.GetDeviceType().GetProductFamilyID() == dev_id) - [array addObject:(id)d.m_dev]; - } - - return DeviceSet(array); -} - -CoreSimulatorSupport::Device CoreSimulatorSupport::DeviceSet::GetFanciest( - CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id) { - Device dev; - - for (NSUInteger i = 0; i < GetNumDevices(); i++) { - Device d(GetDeviceAtIndex(i)); - if (d && d.GetDeviceType() && - d.GetDeviceType().GetProductFamilyID() == dev_id) { - if (!dev) - dev = d; - else { - if ((d.GetDeviceType().GetModelIdentifier() > - dev.GetDeviceType().GetModelIdentifier()) || - d.GetDeviceRuntime().GetVersion() > - dev.GetDeviceRuntime().GetVersion()) - dev = d; - } - } - } - - return dev; -} diff --git a/source/Plugins/Platform/NetBSD/CMakeLists.txt b/source/Plugins/Platform/NetBSD/CMakeLists.txt deleted file mode 100644 index 5e63f10980672..0000000000000 --- a/source/Plugins/Platform/NetBSD/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginPlatformNetBSD PLUGIN - PlatformNetBSD.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbTarget - ) diff --git a/source/Plugins/Platform/OpenBSD/CMakeLists.txt b/source/Plugins/Platform/OpenBSD/CMakeLists.txt deleted file mode 100644 index 8d49e7c4f196b..0000000000000 --- a/source/Plugins/Platform/OpenBSD/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginPlatformOpenBSD PLUGIN - PlatformOpenBSD.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbTarget - ) diff --git a/source/Plugins/Platform/POSIX/CMakeLists.txt b/source/Plugins/Platform/POSIX/CMakeLists.txt deleted file mode 100644 index 749407d63d5c9..0000000000000 --- a/source/Plugins/Platform/POSIX/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginPlatformPOSIX PLUGIN - PlatformPOSIX.cpp - - LINK_LIBS - lldbCore - lldbExpression - lldbHost - lldbInterpreter - lldbTarget - ) diff --git a/source/Plugins/Platform/Windows/CMakeLists.txt b/source/Plugins/Platform/Windows/CMakeLists.txt deleted file mode 100644 index 49a197cdaff36..0000000000000 --- a/source/Plugins/Platform/Windows/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_lldb_library(lldbPluginPlatformWindows PLUGIN - PlatformWindows.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbTarget - ) diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp deleted file mode 100644 index 685d49a73a777..0000000000000 --- a/source/Plugins/Platform/Windows/PlatformWindows.cpp +++ /dev/null @@ -1,593 +0,0 @@ -//===-- PlatformWindows.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "PlatformWindows.h" - -#include <stdio.h> -#if defined(_WIN32) -#include "lldb/Host/windows/windows.h" -#include <winsock2.h> -#endif - -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/BreakpointSite.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/Status.h" - -using namespace lldb; -using namespace lldb_private; - -static uint32_t g_initialize_count = 0; - -namespace { -class SupportedArchList { -public: - SupportedArchList() { - AddArch(ArchSpec("i686-pc-windows")); - AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault)); - AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32)); - AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64)); - AddArch(ArchSpec("i386-pc-windows")); - } - - size_t Count() const { return m_archs.size(); } - - const ArchSpec &operator[](int idx) { return m_archs[idx]; } - -private: - void AddArch(const ArchSpec &spec) { - auto iter = std::find_if( - m_archs.begin(), m_archs.end(), - [spec](const ArchSpec &rhs) { return spec.IsExactMatch(rhs); }); - if (iter != m_archs.end()) - return; - if (spec.IsValid()) - m_archs.push_back(spec); - } - - std::vector<ArchSpec> m_archs; -}; -} // anonymous namespace - -PlatformSP PlatformWindows::CreateInstance(bool force, - const lldb_private::ArchSpec *arch) { - // The only time we create an instance is when we are creating a remote - // windows platform - const bool is_host = false; - - bool create = force; - if (!create && arch && arch->IsValid()) { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) { - case llvm::Triple::PC: - create = true; - break; - - case llvm::Triple::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; - - default: - break; - } - - if (create) { - switch (triple.getOS()) { - case llvm::Triple::Win32: - break; - - case llvm::Triple::UnknownOS: - create = arch->TripleOSWasSpecified(); - break; - - default: - create = false; - break; - } - } - } - if (create) - return PlatformSP(new PlatformWindows(is_host)); - return PlatformSP(); -} - -lldb_private::ConstString PlatformWindows::GetPluginNameStatic(bool is_host) { - if (is_host) { - static ConstString g_host_name(Platform::GetHostPlatformName()); - return g_host_name; - } else { - static ConstString g_remote_name("remote-windows"); - return g_remote_name; - } -} - -const char *PlatformWindows::GetPluginDescriptionStatic(bool is_host) { - return is_host ? "Local Windows user platform plug-in." - : "Remote Windows user platform plug-in."; -} - -lldb_private::ConstString PlatformWindows::GetPluginName() { - return GetPluginNameStatic(IsHost()); -} - -void PlatformWindows::Initialize() { - Platform::Initialize(); - - if (g_initialize_count++ == 0) { -#if defined(_WIN32) - WSADATA dummy; - WSAStartup(MAKEWORD(2, 2), &dummy); - // Force a host flag to true for the default platform object. - PlatformSP default_platform_sp(new PlatformWindows(true)); - default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetHostPlatform(default_platform_sp); -#endif - PluginManager::RegisterPlugin( - PlatformWindows::GetPluginNameStatic(false), - PlatformWindows::GetPluginDescriptionStatic(false), - PlatformWindows::CreateInstance); - } -} - -void PlatformWindows::Terminate(void) { - if (g_initialize_count > 0) { - if (--g_initialize_count == 0) { -#ifdef _WIN32 - WSACleanup(); -#endif - PluginManager::UnregisterPlugin(PlatformWindows::CreateInstance); - } - } - - Platform::Terminate(); -} - -//------------------------------------------------------------------ -/// Default Constructor -//------------------------------------------------------------------ -PlatformWindows::PlatformWindows(bool is_host) : Platform(is_host) {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformWindows::~PlatformWindows() = default; - -bool PlatformWindows::GetModuleSpec(const FileSpec &module_file_spec, - const ArchSpec &arch, - ModuleSpec &module_spec) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch, - module_spec); - - return Platform::GetModuleSpec(module_file_spec, arch, module_spec); -} - -Status PlatformWindows::ResolveExecutable( - const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Status error; - // Nothing special to do here, just use the actual file and architecture - - char exe_path[PATH_MAX]; - ModuleSpec resolved_module_spec(ms); - - if (IsHost()) { - // if we cant resolve the executable loation based on the current path - // variables - if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { - resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - resolved_module_spec.GetFileSpec().SetFile(exe_path, - FileSpec::Style::native); - FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec()); - } - - if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) - FileSystem::Instance().ResolveExecutableLocation( - resolved_module_spec.GetFileSpec()); - - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) - error.Clear(); - else { - ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - error.SetErrorStringWithFormat("unable to find executable for '%s'", - exe_path); - } - } else { - if (m_remote_platform_sp) { - error = GetCachedExecutable(resolved_module_spec, exe_module_sp, nullptr, - *m_remote_platform_sp); - } else { - // We may connect to a process and use the provided executable (Don't use - // local $PATH). - if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) - error.Clear(); - else - error.SetErrorStringWithFormat("the platform is not currently " - "connected, and '%s' doesn't exist in " - "the system root.", - exe_path); - } - } - - if (error.Success()) { - if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - nullptr, nullptr, nullptr); - - if (!exe_module_sp || exe_module_sp->GetObjectFile() == nullptr) { - exe_module_sp.reset(); - error.SetErrorStringWithFormat( - "'%s' doesn't contain the architecture %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - resolved_module_spec.GetArchitecture().GetArchitectureName()); - } - } else { - // No valid architecture was specified, ask the platform for the - // architectures that we should be using (in the correct order) and see - // if we can find a match that way - StreamString arch_names; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - nullptr, nullptr, nullptr); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString( - resolved_module_spec.GetArchitecture().GetArchitectureName()); - } - - if (error.Fail() || !exe_module_sp) { - if (FileSystem::Instance().Readable( - resolved_module_spec.GetFileSpec())) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetData()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } - } - - return error; -} - -bool PlatformWindows::GetRemoteOSVersion() { - if (m_remote_platform_sp) { - m_os_version = m_remote_platform_sp->GetOSVersion(); - return !m_os_version.empty(); - } - return false; -} - -bool PlatformWindows::GetRemoteOSBuildString(std::string &s) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteOSBuildString(s); - s.clear(); - return false; -} - -bool PlatformWindows::GetRemoteOSKernelDescription(std::string &s) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteOSKernelDescription(s); - s.clear(); - return false; -} - -// Remote Platform subclasses need to override this function -ArchSpec PlatformWindows::GetRemoteSystemArchitecture() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteSystemArchitecture(); - return ArchSpec(); -} - -const char *PlatformWindows::GetHostname() { - if (IsHost()) - return Platform::GetHostname(); - - if (m_remote_platform_sp) - return m_remote_platform_sp->GetHostname(); - return nullptr; -} - -bool PlatformWindows::IsConnected() const { - if (IsHost()) - return true; - else if (m_remote_platform_sp) - return m_remote_platform_sp->IsConnected(); - return false; -} - -Status PlatformWindows::ConnectRemote(Args &args) { - Status error; - if (IsHost()) { - error.SetErrorStringWithFormat( - "can't connect to the host platform '%s', always connected", - GetPluginName().AsCString()); - } else { - if (!m_remote_platform_sp) - m_remote_platform_sp = - Platform::Create(ConstString("remote-gdb-server"), error); - - if (m_remote_platform_sp) { - if (error.Success()) { - if (m_remote_platform_sp) { - error = m_remote_platform_sp->ConnectRemote(args); - } else { - error.SetErrorString( - "\"platform connect\" takes a single argument: <connect-url>"); - } - } - } else - error.SetErrorString("failed to create a 'remote-gdb-server' platform"); - - if (error.Fail()) - m_remote_platform_sp.reset(); - } - - return error; -} - -Status PlatformWindows::DisconnectRemote() { - Status error; - - if (IsHost()) { - error.SetErrorStringWithFormat( - "can't disconnect from the host platform '%s', always connected", - GetPluginName().AsCString()); - } else { - if (m_remote_platform_sp) - error = m_remote_platform_sp->DisconnectRemote(); - else - error.SetErrorString("the platform is not currently connected"); - } - return error; -} - -bool PlatformWindows::GetProcessInfo(lldb::pid_t pid, - ProcessInstanceInfo &process_info) { - bool success = false; - if (IsHost()) { - success = Platform::GetProcessInfo(pid, process_info); - } else if (m_remote_platform_sp) { - success = m_remote_platform_sp->GetProcessInfo(pid, process_info); - } - return success; -} - -uint32_t -PlatformWindows::FindProcesses(const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) { - uint32_t match_count = 0; - if (IsHost()) { - // Let the base class figure out the host details - match_count = Platform::FindProcesses(match_info, process_infos); - } else { - // If we are remote, we can only return results if we are connected - if (m_remote_platform_sp) - match_count = - m_remote_platform_sp->FindProcesses(match_info, process_infos); - } - return match_count; -} - -Status PlatformWindows::LaunchProcess(ProcessLaunchInfo &launch_info) { - Status error; - if (IsHost()) { - error = Platform::LaunchProcess(launch_info); - } else { - if (m_remote_platform_sp) - error = m_remote_platform_sp->LaunchProcess(launch_info); - else - error.SetErrorString("the platform is not currently connected"); - } - return error; -} - -ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, - Debugger &debugger, Target *target, - Status &error) { - // Windows has special considerations that must be followed when launching or - // attaching to a process. The key requirement is that when launching or - // attaching to a process, you must do it from the same the thread that will - // go into a permanent loop which will then receive debug events from the - // process. In particular, this means we can't use any of LLDB's generic - // mechanisms to do it for us, because it doesn't have the special knowledge - // required for setting up the background thread or passing the right flags. - // - // Another problem is that that LLDB's standard model for debugging a process - // is to first launch it, have it stop at the entry point, and then attach to - // it. In Windows this doesn't quite work, you have to specify as an - // argument to CreateProcess() that you're going to debug the process. So we - // override DebugProcess here to handle this. Launch operations go directly - // to the process plugin, and attach operations almost go directly to the - // process plugin (but we hijack the events first). In essence, we - // encapsulate all the logic of Launching and Attaching in the process - // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to - // the process plugin. - - if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - // This is a process attach. Don't need to launch anything. - ProcessAttachInfo attach_info(launch_info); - return Attach(attach_info, debugger, target, error); - } else { - ProcessSP process_sp = target->CreateProcess( - launch_info.GetListener(), launch_info.GetProcessPluginName(), nullptr); - - // We need to launch and attach to the process. - launch_info.GetFlags().Set(eLaunchFlagDebug); - if (process_sp) - error = process_sp->Launch(launch_info); - - return process_sp; - } -} - -lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info, - Debugger &debugger, Target *target, - Status &error) { - error.Clear(); - lldb::ProcessSP process_sp; - if (!IsHost()) { - if (m_remote_platform_sp) - process_sp = - m_remote_platform_sp->Attach(attach_info, debugger, target, error); - else - error.SetErrorString("the platform is not currently connected"); - return process_sp; - } - - if (target == nullptr) { - TargetSP new_target_sp; - FileSpec emptyFileSpec; - ArchSpec emptyArchSpec; - - error = debugger.GetTargetList().CreateTarget( - debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); - target = new_target_sp.get(); - } - - if (!target || error.Fail()) - return process_sp; - - debugger.GetTargetList().SetSelectedTarget(target); - - const char *plugin_name = attach_info.GetProcessPluginName(); - process_sp = target->CreateProcess( - attach_info.GetListenerForProcess(debugger), plugin_name, nullptr); - - process_sp->HijackProcessEvents(attach_info.GetHijackListener()); - if (process_sp) - error = process_sp->Attach(attach_info); - - return process_sp; -} - -const char *PlatformWindows::GetUserName(uint32_t uid) { - // Check the cache in Platform in case we have already looked this uid up - const char *user_name = Platform::GetUserName(uid); - if (user_name) - return user_name; - - if (IsRemote() && m_remote_platform_sp) - return m_remote_platform_sp->GetUserName(uid); - return nullptr; -} - -const char *PlatformWindows::GetGroupName(uint32_t gid) { - const char *group_name = Platform::GetGroupName(gid); - if (group_name) - return group_name; - - if (IsRemote() && m_remote_platform_sp) - return m_remote_platform_sp->GetGroupName(gid); - return nullptr; -} - -Status PlatformWindows::GetFileWithUUID(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - if (IsRemote()) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, - local_file); - } - - // Default to the local case - local_file = platform_file; - return Status(); -} - -Status PlatformWindows::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - Status error; - module_sp.reset(); - - if (IsRemote()) { - // If we have a remote platform always, let it try and locate the shared - // module first. - if (m_remote_platform_sp) { - error = m_remote_platform_sp->GetSharedModule( - module_spec, process, module_sp, module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - } - } - - if (!module_sp) { - // Fall back to the local platform and find the file locally - error = Platform::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - } - if (module_sp) - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - return error; -} - -bool PlatformWindows::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { - static SupportedArchList architectures; - - if (idx >= architectures.Count()) - return false; - arch = architectures[idx]; - return true; -} - -void PlatformWindows::GetStatus(Stream &strm) { - Platform::GetStatus(strm); - -#ifdef _WIN32 - llvm::VersionTuple version = HostInfo::GetOSVersion(); - strm << "Host: Windows " << version.getAsString() << '\n'; -#endif -} - -bool PlatformWindows::CanDebugProcess() { return true; } - -Environment PlatformWindows::GetEnvironment() { - if (IsRemote()) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetEnvironment(); - return Environment(); - } - - return Host::GetEnvironment(); -} - -ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) { - if (basename.IsEmpty()) - return basename; - - StreamString stream; - stream.Printf("%s.dll", basename.GetCString()); - return ConstString(stream.GetString()); -} diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h deleted file mode 100644 index f7f55049e4e75..0000000000000 --- a/source/Plugins/Platform/Windows/PlatformWindows.h +++ /dev/null @@ -1,133 +0,0 @@ -//===-- PlatformWindows.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_PlatformWindows_h_ -#define liblldb_PlatformWindows_h_ - -#include "lldb/Target/Platform.h" - -namespace lldb_private { - -class PlatformWindows : public Platform { -public: - PlatformWindows(bool is_host); - - ~PlatformWindows() override; - - static void Initialize(); - - static void Terminate(); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static lldb::PlatformSP CreateInstance(bool force, - const lldb_private::ArchSpec *arch); - - static lldb_private::ConstString GetPluginNameStatic(bool is_host); - - static const char *GetPluginDescriptionStatic(bool is_host); - - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override { return 1; } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - bool GetModuleSpec(const lldb_private::FileSpec &module_file_spec, - const lldb_private::ArchSpec &arch, - lldb_private::ModuleSpec &module_spec) override; - - Status - ResolveExecutable(const lldb_private::ModuleSpec &module_spec, - lldb::ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr) override; - - const char *GetDescription() override { - return GetPluginDescriptionStatic(IsHost()); - } - - bool GetRemoteOSVersion() override; - - bool GetRemoteOSBuildString(std::string &s) override; - - bool GetRemoteOSKernelDescription(std::string &s) override; - - // Remote Platform subclasses need to override this function - lldb_private::ArchSpec GetRemoteSystemArchitecture() override; - - bool IsConnected() const override; - - lldb_private::Status ConnectRemote(lldb_private::Args &args) override; - - lldb_private::Status DisconnectRemote() override; - - const char *GetHostname() override; - - const char *GetUserName(uint32_t uid) override; - - const char *GetGroupName(uint32_t gid) override; - - bool GetProcessInfo(lldb::pid_t pid, - lldb_private::ProcessInstanceInfo &proc_info) override; - - uint32_t - FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info, - lldb_private::ProcessInstanceInfoList &process_infos) override; - - lldb_private::Status - LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; - - lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Status &error) override; - - lldb::ProcessSP Attach(lldb_private::ProcessAttachInfo &attach_info, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Status &error) override; - - lldb_private::Status - GetFileWithUUID(const lldb_private::FileSpec &platform_file, - const lldb_private::UUID *uuid, - lldb_private::FileSpec &local_file) override; - - lldb_private::Status - GetSharedModule(const lldb_private::ModuleSpec &module_spec, - lldb_private::Process *process, lldb::ModuleSP &module_sp, - const lldb_private::FileSpecList *module_search_paths_ptr, - lldb::ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) override; - - bool GetSupportedArchitectureAtIndex(uint32_t idx, - lldb_private::ArchSpec &arch) override; - - void GetStatus(lldb_private::Stream &strm) override; - - bool CanDebugProcess() override; - - Environment GetEnvironment() override; - - // FIXME not sure what the _sigtramp equivalent would be on this platform - void CalculateTrapHandlerSymbolNames() override {} - - ConstString GetFullNameForDylib(ConstString basename) override; - -protected: - lldb::PlatformSP m_remote_platform_sp; - -private: - DISALLOW_COPY_AND_ASSIGN(PlatformWindows); -}; - -} // namespace lldb_private - -#endif // liblldb_PlatformWindows_h_ diff --git a/source/Plugins/Platform/gdb-server/CMakeLists.txt b/source/Plugins/Platform/gdb-server/CMakeLists.txt deleted file mode 100644 index 2e3302590b443..0000000000000 --- a/source/Plugins/Platform/gdb-server/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginPlatformGDB PLUGIN - PlatformRemoteGDBServer.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbTarget - lldbPluginProcessUtility - ) diff --git a/source/Plugins/Process/CMakeLists.txt b/source/Plugins/Process/CMakeLists.txt deleted file mode 100644 index fdeb211fe7a20..0000000000000 --- a/source/Plugins/Process/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") - add_subdirectory(Linux) - add_subdirectory(POSIX) -elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - add_subdirectory(FreeBSD) - add_subdirectory(POSIX) -elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD") - add_subdirectory(NetBSD) - add_subdirectory(POSIX) -elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") - add_subdirectory(Windows/Common) -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX-Kernel) -endif() -add_subdirectory(gdb-remote) -add_subdirectory(Utility) -add_subdirectory(elf-core) -add_subdirectory(mach-core) -add_subdirectory(minidump) diff --git a/source/Plugins/Process/FreeBSD/CMakeLists.txt b/source/Plugins/Process/FreeBSD/CMakeLists.txt deleted file mode 100644 index c8301f350e076..0000000000000 --- a/source/Plugins/Process/FreeBSD/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_lldb_library(lldbPluginProcessFreeBSD PLUGIN - ProcessFreeBSD.cpp - FreeBSDThread.cpp - ProcessMonitor.cpp - - POSIXStopInfo.cpp - RegisterContextPOSIXProcessMonitor_arm.cpp - RegisterContextPOSIXProcessMonitor_arm64.cpp - RegisterContextPOSIXProcessMonitor_powerpc.cpp - RegisterContextPOSIXProcessMonitor_x86.cpp - RegisterContextPOSIXProcessMonitor_mips64.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessUtility - lldbPluginProcessPOSIX - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt deleted file mode 100644 index b4b4c401a271f..0000000000000 --- a/source/Plugins/Process/Linux/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -add_lldb_library(lldbPluginProcessLinux PLUGIN - NativeProcessLinux.cpp - NativeRegisterContextLinux.cpp - NativeRegisterContextLinux_arm.cpp - NativeRegisterContextLinux_arm64.cpp - NativeRegisterContextLinux_mips64.cpp - NativeRegisterContextLinux_ppc64le.cpp - NativeRegisterContextLinux_s390x.cpp - NativeRegisterContextLinux_x86_64.cpp - NativeThreadLinux.cpp - ProcessorTrace.cpp - SingleStepCheck.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessPOSIX - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp deleted file mode 100644 index 8c6c95380e814..0000000000000 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ /dev/null @@ -1,2097 +0,0 @@ -//===-- NativeProcessLinux.cpp -------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "NativeProcessLinux.h" - -#include <errno.h> -#include <stdint.h> -#include <string.h> -#include <unistd.h> - -#include <fstream> -#include <mutex> -#include <sstream> -#include <string> -#include <unordered_map> - -#include "lldb/Core/EmulateInstruction.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostProcess.h" -#include "lldb/Host/PseudoTerminal.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Host/linux/Uio.h" -#include "lldb/Host/posix/ProcessLauncherPosixFork.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StringExtractor.h" -#include "llvm/Support/Errno.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Threading.h" - -#include "NativeThreadLinux.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/LinuxProcMaps.h" -#include "Procfs.h" - -#include <linux/unistd.h> -#include <sys/socket.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <sys/user.h> -#include <sys/wait.h> - -// Support hardware breakpoints in case it has not been defined -#ifndef TRAP_HWBKPT -#define TRAP_HWBKPT 4 -#endif - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; -using namespace llvm; - -// Private bits we only need internally. - -static bool ProcessVmReadvSupported() { - static bool is_supported; - static llvm::once_flag flag; - - llvm::call_once(flag, [] { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - uint32_t source = 0x47424742; - uint32_t dest = 0; - - struct iovec local, remote; - remote.iov_base = &source; - local.iov_base = &dest; - remote.iov_len = local.iov_len = sizeof source; - - // We shall try if cross-process-memory reads work by attempting to read a - // value from our own process. - ssize_t res = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); - is_supported = (res == sizeof(source) && source == dest); - if (is_supported) - LLDB_LOG(log, - "Detected kernel support for process_vm_readv syscall. " - "Fast memory reads enabled."); - else - LLDB_LOG(log, - "syscall process_vm_readv failed (error: {0}). Fast memory " - "reads disabled.", - llvm::sys::StrError()); - }); - - return is_supported; -} - -namespace { -void MaybeLogLaunchInfo(const ProcessLaunchInfo &info) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - if (!log) - return; - - if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) - LLDB_LOG(log, "setting STDIN to '{0}'", action->GetFileSpec()); - else - LLDB_LOG(log, "leaving STDIN as is"); - - if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) - LLDB_LOG(log, "setting STDOUT to '{0}'", action->GetFileSpec()); - else - LLDB_LOG(log, "leaving STDOUT as is"); - - if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) - LLDB_LOG(log, "setting STDERR to '{0}'", action->GetFileSpec()); - else - LLDB_LOG(log, "leaving STDERR as is"); - - int i = 0; - for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; - ++args, ++i) - LLDB_LOG(log, "arg {0}: '{1}'", i, *args); -} - -void DisplayBytes(StreamString &s, void *bytes, uint32_t count) { - uint8_t *ptr = (uint8_t *)bytes; - const uint32_t loop_count = std::min<uint32_t>(DEBUG_PTRACE_MAXBYTES, count); - for (uint32_t i = 0; i < loop_count; i++) { - s.Printf("[%x]", *ptr); - ptr++; - } -} - -void PtraceDisplayBytes(int &req, void *data, size_t data_size) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - if (!log) - return; - StreamString buf; - - switch (req) { - case PTRACE_POKETEXT: { - DisplayBytes(buf, &data, 8); - LLDB_LOGV(log, "PTRACE_POKETEXT {0}", buf.GetData()); - break; - } - case PTRACE_POKEDATA: { - DisplayBytes(buf, &data, 8); - LLDB_LOGV(log, "PTRACE_POKEDATA {0}", buf.GetData()); - break; - } - case PTRACE_POKEUSER: { - DisplayBytes(buf, &data, 8); - LLDB_LOGV(log, "PTRACE_POKEUSER {0}", buf.GetData()); - break; - } - case PTRACE_SETREGS: { - DisplayBytes(buf, data, data_size); - LLDB_LOGV(log, "PTRACE_SETREGS {0}", buf.GetData()); - break; - } - case PTRACE_SETFPREGS: { - DisplayBytes(buf, data, data_size); - LLDB_LOGV(log, "PTRACE_SETFPREGS {0}", buf.GetData()); - break; - } - case PTRACE_SETSIGINFO: { - DisplayBytes(buf, data, sizeof(siginfo_t)); - LLDB_LOGV(log, "PTRACE_SETSIGINFO {0}", buf.GetData()); - break; - } - case PTRACE_SETREGSET: { - // Extract iov_base from data, which is a pointer to the struct iovec - DisplayBytes(buf, *(void **)data, data_size); - LLDB_LOGV(log, "PTRACE_SETREGSET {0}", buf.GetData()); - break; - } - default: {} - } -} - -static constexpr unsigned k_ptrace_word_size = sizeof(void *); -static_assert(sizeof(long) >= k_ptrace_word_size, - "Size of long must be larger than ptrace word size"); -} // end of anonymous namespace - -// Simple helper function to ensure flags are enabled on the given file -// descriptor. -static Status EnsureFDFlags(int fd, int flags) { - Status error; - - int status = fcntl(fd, F_GETFL); - if (status == -1) { - error.SetErrorToErrno(); - return error; - } - - if (fcntl(fd, F_SETFL, status | flags) == -1) { - error.SetErrorToErrno(); - return error; - } - - return error; -} - -// ----------------------------------------------------------------------------- -// Public Static Methods -// ----------------------------------------------------------------------------- - -llvm::Expected<std::unique_ptr<NativeProcessProtocol>> -NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info, - NativeDelegate &native_delegate, - MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - MaybeLogLaunchInfo(launch_info); - - Status status; - ::pid_t pid = ProcessLauncherPosixFork() - .LaunchProcess(launch_info, status) - .GetProcessId(); - LLDB_LOG(log, "pid = {0:x}", pid); - if (status.Fail()) { - LLDB_LOG(log, "failed to launch process: {0}", status); - return status.ToError(); - } - - // Wait for the child process to trap on its call to execve. - int wstatus; - ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0); - assert(wpid == pid); - (void)wpid; - if (!WIFSTOPPED(wstatus)) { - LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}", - WaitStatus::Decode(wstatus)); - return llvm::make_error<StringError>("Could not sync with inferior process", - llvm::inconvertibleErrorCode()); - } - LLDB_LOG(log, "inferior started, now in stopped state"); - - ProcessInstanceInfo Info; - if (!Host::GetProcessInfo(pid, Info)) { - return llvm::make_error<StringError>("Cannot get process architecture", - llvm::inconvertibleErrorCode()); - } - - // Set the architecture to the exe architecture. - LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid, - Info.GetArchitecture().GetArchitectureName()); - - status = SetDefaultPtraceOpts(pid); - if (status.Fail()) { - LLDB_LOG(log, "failed to set default ptrace options: {0}", status); - return status.ToError(); - } - - return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux( - pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate, - Info.GetArchitecture(), mainloop, {pid})); -} - -llvm::Expected<std::unique_ptr<NativeProcessProtocol>> -NativeProcessLinux::Factory::Attach( - lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, - MainLoop &mainloop) const { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid = {0:x}", pid); - - // Retrieve the architecture for the running process. - ProcessInstanceInfo Info; - if (!Host::GetProcessInfo(pid, Info)) { - return llvm::make_error<StringError>("Cannot get process architecture", - llvm::inconvertibleErrorCode()); - } - - auto tids_or = NativeProcessLinux::Attach(pid); - if (!tids_or) - return tids_or.takeError(); - - return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux( - pid, -1, native_delegate, Info.GetArchitecture(), mainloop, *tids_or)); -} - -// ----------------------------------------------------------------------------- -// Public Instance Methods -// ----------------------------------------------------------------------------- - -NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, - NativeDelegate &delegate, - const ArchSpec &arch, MainLoop &mainloop, - llvm::ArrayRef<::pid_t> tids) - : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) { - if (m_terminal_fd != -1) { - Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); - assert(status.Success()); - } - - Status status; - m_sigchld_handle = mainloop.RegisterSignal( - SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status); - assert(m_sigchld_handle && status.Success()); - - for (const auto &tid : tids) { - NativeThreadLinux &thread = AddThread(tid); - thread.SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(thread); - } - - // Let our process instance know the thread has stopped. - SetCurrentThreadID(tids[0]); - SetState(StateType::eStateStopped, false); - - // Proccess any signals we received before installing our handler - SigchldHandler(); -} - -llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - Status status; - // Use a map to keep track of the threads which we have attached/need to - // attach. - Host::TidMap tids_to_attach; - while (Host::FindProcessThreads(pid, tids_to_attach)) { - for (Host::TidMap::iterator it = tids_to_attach.begin(); - it != tids_to_attach.end();) { - if (it->second == false) { - lldb::tid_t tid = it->first; - - // Attach to the requested process. - // An attach will cause the thread to stop with a SIGSTOP. - if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) { - // No such thread. The thread may have exited. More error handling - // may be needed. - if (status.GetError() == ESRCH) { - it = tids_to_attach.erase(it); - continue; - } - return status.ToError(); - } - - int wpid = - llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL); - // Need to use __WALL otherwise we receive an error with errno=ECHLD At - // this point we should have a thread stopped if waitpid succeeds. - if (wpid < 0) { - // No such thread. The thread may have exited. More error handling - // may be needed. - if (errno == ESRCH) { - it = tids_to_attach.erase(it); - continue; - } - return llvm::errorCodeToError( - std::error_code(errno, std::generic_category())); - } - - if ((status = SetDefaultPtraceOpts(tid)).Fail()) - return status.ToError(); - - LLDB_LOG(log, "adding tid = {0}", tid); - it->second = true; - } - - // move the loop forward - ++it; - } - } - - size_t tid_count = tids_to_attach.size(); - if (tid_count == 0) - return llvm::make_error<StringError>("No such process", - llvm::inconvertibleErrorCode()); - - std::vector<::pid_t> tids; - tids.reserve(tid_count); - for (const auto &p : tids_to_attach) - tids.push_back(p.first); - return std::move(tids); -} - -Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) { - long ptrace_opts = 0; - - // Have the child raise an event on exit. This is used to keep the child in - // limbo until it is destroyed. - ptrace_opts |= PTRACE_O_TRACEEXIT; - - // Have the tracer trace threads which spawn in the inferior process. - // TODO: if we want to support tracing the inferiors' child, add the - // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK) - ptrace_opts |= PTRACE_O_TRACECLONE; - - // Have the tracer notify us before execve returns (needed to disable legacy - // SIGTRAP generation) - ptrace_opts |= PTRACE_O_TRACEEXEC; - - return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts); -} - -// Handles all waitpid events from the inferior process. -void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, - WaitStatus status) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - - // Certain activities differ based on whether the pid is the tid of the main - // thread. - const bool is_main_thread = (pid == GetID()); - - // Handle when the thread exits. - if (exited) { - LLDB_LOG(log, - "got exit signal({0}) , tid = {1} ({2} main thread), process " - "state = {3}", - signal, pid, is_main_thread ? "is" : "is not", GetState()); - - // This is a thread that exited. Ensure we're not tracking it anymore. - StopTrackingThread(pid); - - if (is_main_thread) { - // The main thread exited. We're done monitoring. Report to delegate. - SetExitStatus(status, true); - - // Notify delegate that our process has exited. - SetState(StateType::eStateExited, true); - } - return; - } - - siginfo_t info; - const auto info_err = GetSignalInfo(pid, &info); - auto thread_sp = GetThreadByID(pid); - - if (!thread_sp) { - // Normally, the only situation when we cannot find the thread is if we - // have just received a new thread notification. This is indicated by - // GetSignalInfo() returning si_code == SI_USER and si_pid == 0 - LLDB_LOG(log, "received notification about an unknown tid {0}.", pid); - - if (info_err.Fail()) { - LLDB_LOG(log, - "(tid {0}) GetSignalInfo failed ({1}). " - "Ingoring this notification.", - pid, info_err); - return; - } - - LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code, - info.si_pid); - - NativeThreadLinux &thread = AddThread(pid); - - // Resume the newly created thread. - ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(thread); - return; - } - - // Get details on the signal raised. - if (info_err.Success()) { - // We have retrieved the signal info. Dispatch appropriately. - if (info.si_signo == SIGTRAP) - MonitorSIGTRAP(info, *thread_sp); - else - MonitorSignal(info, *thread_sp, exited); - } else { - if (info_err.GetError() == EINVAL) { - // This is a group stop reception for this tid. We can reach here if we - // reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the tracee, - // triggering the group-stop mechanism. Normally receiving these would - // stop the process, pending a SIGCONT. Simulating this state in a - // debugger is hard and is generally not needed (one use case is - // debugging background task being managed by a shell). For general use, - // it is sufficient to stop the process in a signal-delivery stop which - // happens before the group stop. This done by MonitorSignal and works - // correctly for all signals. - LLDB_LOG(log, - "received a group stop for pid {0} tid {1}. Transparent " - "handling of group stops not supported, resuming the " - "thread.", - GetID(), pid); - ResumeThread(*thread_sp, thread_sp->GetState(), - LLDB_INVALID_SIGNAL_NUMBER); - } else { - // ptrace(GETSIGINFO) failed (but not due to group-stop). - - // A return value of ESRCH means the thread/process is no longer on the - // system, so it was killed somehow outside of our control. Either way, - // we can't do anything with it anymore. - - // Stop tracking the metadata for the thread since it's entirely off the - // system now. - const bool thread_found = StopTrackingThread(pid); - - LLDB_LOG(log, - "GetSignalInfo failed: {0}, tid = {1}, signal = {2}, " - "status = {3}, main_thread = {4}, thread_found: {5}", - info_err, pid, signal, status, is_main_thread, thread_found); - - if (is_main_thread) { - // Notify the delegate - our process is not available but appears to - // have been killed outside our control. Is eStateExited the right - // exit state in this case? - SetExitStatus(status, true); - SetState(StateType::eStateExited, true); - } else { - // This thread was pulled out from underneath us. Anything to do here? - // Do we want to do an all stop? - LLDB_LOG(log, - "pid {0} tid {1} non-main thread exit occurred, didn't " - "tell delegate anything since thread disappeared out " - "from underneath us", - GetID(), pid); - } - } - } -} - -void NativeProcessLinux::WaitForNewThread(::pid_t tid) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - if (GetThreadByID(tid)) { - // We are already tracking the thread - we got the event on the new thread - // (see MonitorSignal) before this one. We are done. - return; - } - - // The thread is not tracked yet, let's wait for it to appear. - int status = -1; - LLDB_LOG(log, - "received thread creation event for tid {0}. tid not tracked " - "yet, waiting for thread to appear...", - tid); - ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL); - // Since we are waiting on a specific tid, this must be the creation event. - // But let's do some checks just in case. - if (wait_pid != tid) { - LLDB_LOG(log, - "waiting for tid {0} failed. Assuming the thread has " - "disappeared in the meantime", - tid); - // The only way I know of this could happen is if the whole process was - // SIGKILLed in the mean time. In any case, we can't do anything about that - // now. - return; - } - if (WIFEXITED(status)) { - LLDB_LOG(log, - "waiting for tid {0} returned an 'exited' event. Not " - "tracking the thread.", - tid); - // Also a very improbable event. - return; - } - - LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid); - NativeThreadLinux &new_thread = AddThread(tid); - - ResumeThread(new_thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(new_thread); -} - -void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, - NativeThreadLinux &thread) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - const bool is_main_thread = (thread.GetID() == GetID()); - - assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); - - switch (info.si_code) { - // TODO: these two cases are required if we want to support tracing of the - // inferiors' children. We'd need this to debug a monitor. case (SIGTRAP | - // (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): - - case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): { - // This is the notification on the parent thread which informs us of new - // thread creation. We don't want to do anything with the parent thread so - // we just resume it. In case we want to implement "break on thread - // creation" functionality, we would need to stop here. - - unsigned long event_message = 0; - if (GetEventMessage(thread.GetID(), &event_message).Fail()) { - LLDB_LOG(log, - "pid {0} received thread creation event but " - "GetEventMessage failed so we don't know the new tid", - thread.GetID()); - } else - WaitForNewThread(event_message); - - ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); - break; - } - - case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { - LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP); - - // Exec clears any pending notifications. - m_pending_notification_tid = LLDB_INVALID_THREAD_ID; - - // Remove all but the main thread here. Linux fork creates a new process - // which only copies the main thread. - LLDB_LOG(log, "exec received, stop tracking all but main thread"); - - for (auto i = m_threads.begin(); i != m_threads.end();) { - if ((*i)->GetID() == GetID()) - i = m_threads.erase(i); - else - ++i; - } - assert(m_threads.size() == 1); - auto *main_thread = static_cast<NativeThreadLinux *>(m_threads[0].get()); - - SetCurrentThreadID(main_thread->GetID()); - main_thread->SetStoppedByExec(); - - // Tell coordinator about about the "new" (since exec) stopped main thread. - ThreadWasCreated(*main_thread); - - // Let our delegate know we have just exec'd. - NotifyDidExec(); - - // Let the process know we're stopped. - StopRunningThreads(main_thread->GetID()); - - break; - } - - case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { - // The inferior process or one of its threads is about to exit. We don't - // want to do anything with the thread so we just resume it. In case we - // want to implement "break on thread exit" functionality, we would need to - // stop here. - - unsigned long data = 0; - if (GetEventMessage(thread.GetID(), &data).Fail()) - data = -1; - - LLDB_LOG(log, - "received PTRACE_EVENT_EXIT, data = {0:x}, WIFEXITED={1}, " - "WIFSIGNALED={2}, pid = {3}, main_thread = {4}", - data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(), - is_main_thread); - - - StateType state = thread.GetState(); - if (!StateIsRunningState(state)) { - // Due to a kernel bug, we may sometimes get this stop after the inferior - // gets a SIGKILL. This confuses our state tracking logic in - // ResumeThread(), since normally, we should not be receiving any ptrace - // events while the inferior is stopped. This makes sure that the - // inferior is resumed and exits normally. - state = eStateRunning; - } - ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER); - - break; - } - - case 0: - case TRAP_TRACE: // We receive this on single stepping. - case TRAP_HWBKPT: // We receive this on watchpoint hit - { - // If a watchpoint was hit, report it - uint32_t wp_index; - Status error = thread.GetRegisterContext().GetWatchpointHitIndex( - wp_index, (uintptr_t)info.si_addr); - if (error.Fail()) - LLDB_LOG(log, - "received error while checking for watchpoint hits, pid = " - "{0}, error = {1}", - thread.GetID(), error); - if (wp_index != LLDB_INVALID_INDEX32) { - MonitorWatchpoint(thread, wp_index); - break; - } - - // If a breakpoint was hit, report it - uint32_t bp_index; - error = thread.GetRegisterContext().GetHardwareBreakHitIndex( - bp_index, (uintptr_t)info.si_addr); - if (error.Fail()) - LLDB_LOG(log, "received error while checking for hardware " - "breakpoint hits, pid = {0}, error = {1}", - thread.GetID(), error); - if (bp_index != LLDB_INVALID_INDEX32) { - MonitorBreakpoint(thread); - break; - } - - // Otherwise, report step over - MonitorTrace(thread); - break; - } - - case SI_KERNEL: -#if defined __mips__ - // For mips there is no special signal for watchpoint So we check for - // watchpoint in kernel trap - { - // If a watchpoint was hit, report it - uint32_t wp_index; - Status error = thread.GetRegisterContext().GetWatchpointHitIndex( - wp_index, LLDB_INVALID_ADDRESS); - if (error.Fail()) - LLDB_LOG(log, - "received error while checking for watchpoint hits, pid = " - "{0}, error = {1}", - thread.GetID(), error); - if (wp_index != LLDB_INVALID_INDEX32) { - MonitorWatchpoint(thread, wp_index); - break; - } - } -// NO BREAK -#endif - case TRAP_BRKPT: - MonitorBreakpoint(thread); - break; - - case SIGTRAP: - case (SIGTRAP | 0x80): - LLDB_LOG( - log, - "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}, resuming", - info.si_code, GetID(), thread.GetID()); - - // Ignore these signals until we know more about them. - ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER); - break; - - default: - LLDB_LOG(log, "received unknown SIGTRAP stop event ({0}, pid {1} tid {2}", - info.si_code, GetID(), thread.GetID()); - MonitorSignal(info, thread, false); - break; - } -} - -void NativeProcessLinux::MonitorTrace(NativeThreadLinux &thread) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "received trace event, pid = {0}", thread.GetID()); - - // This thread is currently stopped. - thread.SetStoppedByTrace(); - - StopRunningThreads(thread.GetID()); -} - -void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) { - Log *log( - GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); - LLDB_LOG(log, "received breakpoint event, pid = {0}", thread.GetID()); - - // Mark the thread as stopped at breakpoint. - thread.SetStoppedByBreakpoint(); - FixupBreakpointPCAsNeeded(thread); - - if (m_threads_stepping_with_breakpoint.find(thread.GetID()) != - m_threads_stepping_with_breakpoint.end()) - thread.SetStoppedByTrace(); - - StopRunningThreads(thread.GetID()); -} - -void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread, - uint32_t wp_index) { - Log *log( - GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_WATCHPOINTS)); - LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}", - thread.GetID(), wp_index); - - // Mark the thread as stopped at watchpoint. The address is at - // (lldb::addr_t)info->si_addr if we need it. - thread.SetStoppedByWatchpoint(wp_index); - - // We need to tell all other running threads before we notify the delegate - // about this stop. - StopRunningThreads(thread.GetID()); -} - -void NativeProcessLinux::MonitorSignal(const siginfo_t &info, - NativeThreadLinux &thread, bool exited) { - const int signo = info.si_signo; - const bool is_from_llgs = info.si_pid == getpid(); - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // POSIX says that process behaviour is undefined after it ignores a SIGFPE, - // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2) - // or raise(3). Similarly for tgkill(2) on Linux. - // - // IOW, user generated signals never generate what we consider to be a - // "crash". - // - // Similarly, ACK signals generated by this monitor. - - // Handle the signal. - LLDB_LOG(log, - "received signal {0} ({1}) with code {2}, (siginfo pid = {3}, " - "waitpid pid = {4})", - Host::GetSignalAsCString(signo), signo, info.si_code, - thread.GetID()); - - // Check for thread stop notification. - if (is_from_llgs && (info.si_code == SI_TKILL) && (signo == SIGSTOP)) { - // This is a tgkill()-based stop. - LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID()); - - // Check that we're not already marked with a stop reason. Note this thread - // really shouldn't already be marked as stopped - if we were, that would - // imply that the kernel signaled us with the thread stopping which we - // handled and marked as stopped, and that, without an intervening resume, - // we received another stop. It is more likely that we are missing the - // marking of a run state somewhere if we find that the thread was marked - // as stopped. - const StateType thread_state = thread.GetState(); - if (!StateIsStoppedState(thread_state, false)) { - // An inferior thread has stopped because of a SIGSTOP we have sent it. - // Generally, these are not important stops and we don't want to report - // them as they are just used to stop other threads when one thread (the - // one with the *real* stop reason) hits a breakpoint (watchpoint, - // etc...). However, in the case of an asynchronous Interrupt(), this - // *is* the real stop reason, so we leave the signal intact if this is - // the thread that was chosen as the triggering thread. - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { - if (m_pending_notification_tid == thread.GetID()) - thread.SetStoppedBySignal(SIGSTOP, &info); - else - thread.SetStoppedWithNoReason(); - - SetCurrentThreadID(thread.GetID()); - SignalIfAllThreadsStopped(); - } else { - // We can end up here if stop was initiated by LLGS but by this time a - // thread stop has occurred - maybe initiated by another event. - Status error = ResumeThread(thread, thread.GetState(), 0); - if (error.Fail()) - LLDB_LOG(log, "failed to resume thread {0}: {1}", thread.GetID(), - error); - } - } else { - LLDB_LOG(log, - "pid {0} tid {1}, thread was already marked as a stopped " - "state (state={2}), leaving stop signal as is", - GetID(), thread.GetID(), thread_state); - SignalIfAllThreadsStopped(); - } - - // Done handling. - return; - } - - // Check if debugger should stop at this signal or just ignore it and resume - // the inferior. - if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) { - ResumeThread(thread, thread.GetState(), signo); - return; - } - - // This thread is stopped. - LLDB_LOG(log, "received signal {0}", Host::GetSignalAsCString(signo)); - thread.SetStoppedBySignal(signo, &info); - - // Send a stop to the debugger after we get all other threads to stop. - StopRunningThreads(thread.GetID()); -} - -namespace { - -struct EmulatorBaton { - NativeProcessLinux &m_process; - NativeRegisterContext &m_reg_context; - - // eRegisterKindDWARF -> RegsiterValue - std::unordered_map<uint32_t, RegisterValue> m_register_values; - - EmulatorBaton(NativeProcessLinux &process, NativeRegisterContext ®_context) - : m_process(process), m_reg_context(reg_context) {} -}; - -} // anonymous namespace - -static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, void *dst, size_t length) { - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - - size_t bytes_read; - emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read); - return bytes_read; -} - -static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) { - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - - auto it = emulator_baton->m_register_values.find( - reg_info->kinds[eRegisterKindDWARF]); - if (it != emulator_baton->m_register_values.end()) { - reg_value = it->second; - return true; - } - - // The emulator only fill in the dwarf regsiter numbers (and in some case the - // generic register numbers). Get the full register info from the register - // context based on the dwarf register numbers. - const RegisterInfo *full_reg_info = - emulator_baton->m_reg_context.GetRegisterInfo( - eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); - - Status error = - emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value); - if (error.Success()) - return true; - - return false; -} - -static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) { - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - emulator_baton->m_register_values[reg_info->kinds[eRegisterKindDWARF]] = - reg_value; - return true; -} - -static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, const void *dst, - size_t length) { - return length; -} - -static lldb::addr_t ReadFlags(NativeRegisterContext ®siter_context) { - const RegisterInfo *flags_info = regsiter_context.GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - return regsiter_context.ReadRegisterAsUnsigned(flags_info, - LLDB_INVALID_ADDRESS); -} - -Status -NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { - Status error; - NativeRegisterContext& register_context = thread.GetRegisterContext(); - - std::unique_ptr<EmulateInstruction> emulator_ap( - EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, - nullptr)); - - if (emulator_ap == nullptr) - return Status("Instruction emulator not found!"); - - EmulatorBaton baton(*this, register_context); - emulator_ap->SetBaton(&baton); - emulator_ap->SetReadMemCallback(&ReadMemoryCallback); - emulator_ap->SetReadRegCallback(&ReadRegisterCallback); - emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); - emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); - - if (!emulator_ap->ReadInstruction()) - return Status("Read instruction failed!"); - - bool emulation_result = - emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); - - const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - - auto pc_it = - baton.m_register_values.find(reg_info_pc->kinds[eRegisterKindDWARF]); - auto flags_it = - baton.m_register_values.find(reg_info_flags->kinds[eRegisterKindDWARF]); - - lldb::addr_t next_pc; - lldb::addr_t next_flags; - if (emulation_result) { - assert(pc_it != baton.m_register_values.end() && - "Emulation was successfull but PC wasn't updated"); - next_pc = pc_it->second.GetAsUInt64(); - - if (flags_it != baton.m_register_values.end()) - next_flags = flags_it->second.GetAsUInt64(); - else - next_flags = ReadFlags(register_context); - } else if (pc_it == baton.m_register_values.end()) { - // Emulate instruction failed and it haven't changed PC. Advance PC with - // the size of the current opcode because the emulation of all - // PC modifying instruction should be successful. The failure most - // likely caused by a not supported instruction which don't modify PC. - next_pc = register_context.GetPC() + emulator_ap->GetOpcode().GetByteSize(); - next_flags = ReadFlags(register_context); - } else { - // The instruction emulation failed after it modified the PC. It is an - // unknown error where we can't continue because the next instruction is - // modifying the PC but we don't know how. - return Status("Instruction emulation failed unexpectedly."); - } - - if (m_arch.GetMachine() == llvm::Triple::arm) { - if (next_flags & 0x20) { - // Thumb mode - error = SetSoftwareBreakpoint(next_pc, 2); - } else { - // Arm mode - error = SetSoftwareBreakpoint(next_pc, 4); - } - } else if (m_arch.GetMachine() == llvm::Triple::mips64 || - m_arch.GetMachine() == llvm::Triple::mips64el || - m_arch.GetMachine() == llvm::Triple::mips || - m_arch.GetMachine() == llvm::Triple::mipsel || - m_arch.GetMachine() == llvm::Triple::ppc64le) - error = SetSoftwareBreakpoint(next_pc, 4); - else { - // No size hint is given for the next breakpoint - error = SetSoftwareBreakpoint(next_pc, 0); - } - - // If setting the breakpoint fails because next_pc is out of the address - // space, ignore it and let the debugee segfault. - if (error.GetError() == EIO || error.GetError() == EFAULT) { - return Status(); - } else if (error.Fail()) - return error; - - m_threads_stepping_with_breakpoint.insert({thread.GetID(), next_pc}); - - return Status(); -} - -bool NativeProcessLinux::SupportHardwareSingleStepping() const { - if (m_arch.GetMachine() == llvm::Triple::arm || - m_arch.GetMachine() == llvm::Triple::mips64 || - m_arch.GetMachine() == llvm::Triple::mips64el || - m_arch.GetMachine() == llvm::Triple::mips || - m_arch.GetMachine() == llvm::Triple::mipsel) - return false; - return true; -} - -Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid {0}", GetID()); - - bool software_single_step = !SupportHardwareSingleStepping(); - - if (software_single_step) { - for (const auto &thread : m_threads) { - assert(thread && "thread list should not contain NULL threads"); - - const ResumeAction *const action = - resume_actions.GetActionForThread(thread->GetID(), true); - if (action == nullptr) - continue; - - if (action->state == eStateStepping) { - Status error = SetupSoftwareSingleStepping( - static_cast<NativeThreadLinux &>(*thread)); - if (error.Fail()) - return error; - } - } - } - - for (const auto &thread : m_threads) { - assert(thread && "thread list should not contain NULL threads"); - - const ResumeAction *const action = - resume_actions.GetActionForThread(thread->GetID(), true); - - if (action == nullptr) { - LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread->GetID()); - continue; - } - - LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", - action->state, GetID(), thread->GetID()); - - switch (action->state) { - case eStateRunning: - case eStateStepping: { - // Run the thread, possibly feeding it the signal. - const int signo = action->signal; - ResumeThread(static_cast<NativeThreadLinux &>(*thread), action->state, - signo); - break; - } - - case eStateSuspended: - case eStateStopped: - llvm_unreachable("Unexpected state"); - - default: - return Status("NativeProcessLinux::%s (): unexpected state %s specified " - "for pid %" PRIu64 ", tid %" PRIu64, - __FUNCTION__, StateAsCString(action->state), GetID(), - thread->GetID()); - } - } - - return Status(); -} - -Status NativeProcessLinux::Halt() { - Status error; - - if (kill(GetID(), SIGSTOP) != 0) - error.SetErrorToErrno(); - - return error; -} - -Status NativeProcessLinux::Detach() { - Status error; - - // Stop monitoring the inferior. - m_sigchld_handle.reset(); - - // Tell ptrace to detach from the process. - if (GetID() == LLDB_INVALID_PROCESS_ID) - return error; - - for (const auto &thread : m_threads) { - Status e = Detach(thread->GetID()); - if (e.Fail()) - error = - e; // Save the error, but still attempt to detach from other threads. - } - - m_processor_trace_monitor.clear(); - m_pt_proces_trace_id = LLDB_INVALID_UID; - - return error; -} - -Status NativeProcessLinux::Signal(int signo) { - Status error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo, - Host::GetSignalAsCString(signo), GetID()); - - if (kill(GetID(), signo)) - error.SetErrorToErrno(); - - return error; -} - -Status NativeProcessLinux::Interrupt() { - // Pick a running thread (or if none, a not-dead stopped thread) as the - // chosen thread that will be the stop-reason thread. - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - NativeThreadProtocol *running_thread = nullptr; - NativeThreadProtocol *stopped_thread = nullptr; - - LLDB_LOG(log, "selecting running thread for interrupt target"); - for (const auto &thread : m_threads) { - // If we have a running or stepping thread, we'll call that the target of - // the interrupt. - const auto thread_state = thread->GetState(); - if (thread_state == eStateRunning || thread_state == eStateStepping) { - running_thread = thread.get(); - break; - } else if (!stopped_thread && StateIsStoppedState(thread_state, true)) { - // Remember the first non-dead stopped thread. We'll use that as a - // backup if there are no running threads. - stopped_thread = thread.get(); - } - } - - if (!running_thread && !stopped_thread) { - Status error("found no running/stepping or live stopped threads as target " - "for interrupt"); - LLDB_LOG(log, "skipping due to error: {0}", error); - - return error; - } - - NativeThreadProtocol *deferred_signal_thread = - running_thread ? running_thread : stopped_thread; - - LLDB_LOG(log, "pid {0} {1} tid {2} chosen for interrupt target", GetID(), - running_thread ? "running" : "stopped", - deferred_signal_thread->GetID()); - - StopRunningThreads(deferred_signal_thread->GetID()); - - return Status(); -} - -Status NativeProcessLinux::Kill() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "pid {0}", GetID()); - - Status error; - - switch (m_state) { - case StateType::eStateInvalid: - case StateType::eStateExited: - case StateType::eStateCrashed: - case StateType::eStateDetached: - case StateType::eStateUnloaded: - // Nothing to do - the process is already dead. - LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), - m_state); - return error; - - case StateType::eStateConnected: - case StateType::eStateAttaching: - case StateType::eStateLaunching: - case StateType::eStateStopped: - case StateType::eStateRunning: - case StateType::eStateStepping: - case StateType::eStateSuspended: - // We can try to kill a process in these states. - break; - } - - if (kill(GetID(), SIGKILL) != 0) { - error.SetErrorToErrno(); - return error; - } - - return error; -} - -Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) { - // FIXME review that the final memory region returned extends to the end of - // the virtual address space, - // with no perms if it is not mapped. - - // Use an approach that reads memory regions from /proc/{pid}/maps. Assume - // proc maps entries are in ascending order. - // FIXME assert if we find differently. - - if (m_supports_mem_region == LazyBool::eLazyBoolNo) { - // We're done. - return Status("unsupported"); - } - - Status error = PopulateMemoryRegionCache(); - if (error.Fail()) { - return error; - } - - lldb::addr_t prev_base_address = 0; - - // FIXME start by finding the last region that is <= target address using - // binary search. Data is sorted. - // There can be a ton of regions on pthreads apps with lots of threads. - for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end(); - ++it) { - MemoryRegionInfo &proc_entry_info = it->first; - - // Sanity check assumption that /proc/{pid}/maps entries are ascending. - assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) && - "descending /proc/pid/maps entries detected, unexpected"); - prev_base_address = proc_entry_info.GetRange().GetRangeBase(); - UNUSED_IF_ASSERT_DISABLED(prev_base_address); - - // If the target address comes before this entry, indicate distance to next - // region. - if (load_addr < proc_entry_info.GetRange().GetRangeBase()) { - range_info.GetRange().SetRangeBase(load_addr); - range_info.GetRange().SetByteSize( - proc_entry_info.GetRange().GetRangeBase() - load_addr); - range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); - - return error; - } else if (proc_entry_info.GetRange().Contains(load_addr)) { - // The target address is within the memory region we're processing here. - range_info = proc_entry_info; - return error; - } - - // The target memory address comes somewhere after the region we just - // parsed. - } - - // If we made it here, we didn't find an entry that contained the given - // address. Return the load_addr as start and the amount of bytes betwwen - // load address and the end of the memory as size. - range_info.GetRange().SetRangeBase(load_addr); - range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo); - range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); - return error; -} - -Status NativeProcessLinux::PopulateMemoryRegionCache() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - - // If our cache is empty, pull the latest. There should always be at least - // one memory region if memory region handling is supported. - if (!m_mem_region_cache.empty()) { - LLDB_LOG(log, "reusing {0} cached memory region entries", - m_mem_region_cache.size()); - return Status(); - } - - auto BufferOrError = getProcFile(GetID(), "maps"); - if (!BufferOrError) { - m_supports_mem_region = LazyBool::eLazyBoolNo; - return BufferOrError.getError(); - } - Status Result; - ParseLinuxMapRegions(BufferOrError.get()->getBuffer(), - [&](const MemoryRegionInfo &Info, const Status &ST) { - if (ST.Success()) { - FileSpec file_spec(Info.GetName().GetCString()); - FileSystem::Instance().Resolve(file_spec); - m_mem_region_cache.emplace_back(Info, file_spec); - return true; - } else { - m_supports_mem_region = LazyBool::eLazyBoolNo; - LLDB_LOG(log, "failed to parse proc maps: {0}", ST); - Result = ST; - return false; - } - }); - if (Result.Fail()) - return Result; - - if (m_mem_region_cache.empty()) { - // No entries after attempting to read them. This shouldn't happen if - // /proc/{pid}/maps is supported. Assume we don't support map entries via - // procfs. - m_supports_mem_region = LazyBool::eLazyBoolNo; - LLDB_LOG(log, - "failed to find any procfs maps entries, assuming no support " - "for memory region metadata retrieval"); - return Status("not supported"); - } - - LLDB_LOG(log, "read {0} memory region entries from /proc/{1}/maps", - m_mem_region_cache.size(), GetID()); - - // We support memory retrieval, remember that. - m_supports_mem_region = LazyBool::eLazyBoolYes; - return Status(); -} - -void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, "newBumpId={0}", newBumpId); - LLDB_LOG(log, "clearing {0} entries from memory region cache", - m_mem_region_cache.size()); - m_mem_region_cache.clear(); -} - -Status NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions, - lldb::addr_t &addr) { -// FIXME implementing this requires the equivalent of -// InferiorCallPOSIX::InferiorCallMmap, which depends on functional ThreadPlans -// working with Native*Protocol. -#if 1 - return Status("not implemented yet"); -#else - addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - // TODO implement this directly in NativeProcessLinux - // (and lift to NativeProcessPOSIX if/when that class is refactored out). - if (InferiorCallMmap(this, addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[addr] = size; - return Status(); - } else { - addr = LLDB_INVALID_ADDRESS; - return Status("unable to allocate %" PRIu64 - " bytes of memory with permissions %s", - size, GetPermissionsAsCString(permissions)); - } -#endif -} - -Status NativeProcessLinux::DeallocateMemory(lldb::addr_t addr) { - // FIXME see comments in AllocateMemory - required lower-level - // bits not in place yet (ThreadPlans) - return Status("not implemented"); -} - -lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() { - // punt on this for now - return LLDB_INVALID_ADDRESS; -} - -size_t NativeProcessLinux::UpdateThreads() { - // The NativeProcessLinux monitoring threads are always up to date with - // respect to thread state and they keep the thread list populated properly. - // All this method needs to do is return the thread count. - return m_threads.size(); -} - -Status NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size, - bool hardware) { - if (hardware) - return SetHardwareBreakpoint(addr, size); - else - return SetSoftwareBreakpoint(addr, size); -} - -Status NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { - if (hardware) - return RemoveHardwareBreakpoint(addr); - else - return NativeProcessProtocol::RemoveBreakpoint(addr); -} - -llvm::Expected<llvm::ArrayRef<uint8_t>> -NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { - // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the - // linux kernel does otherwise. - static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7}; - static const uint8_t g_thumb_opcode[] = {0x01, 0xde}; - - switch (GetArchitecture().GetMachine()) { - case llvm::Triple::arm: - switch (size_hint) { - case 2: - return llvm::makeArrayRef(g_thumb_opcode); - case 4: - return llvm::makeArrayRef(g_arm_opcode); - default: - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "Unrecognised trap opcode size hint!"); - } - default: - return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint); - } -} - -Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size, - size_t &bytes_read) { - if (ProcessVmReadvSupported()) { - // The process_vm_readv path is about 50 times faster than ptrace api. We - // want to use this syscall if it is supported. - - const ::pid_t pid = GetID(); - - struct iovec local_iov, remote_iov; - local_iov.iov_base = buf; - local_iov.iov_len = size; - remote_iov.iov_base = reinterpret_cast<void *>(addr); - remote_iov.iov_len = size; - - bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0); - const bool success = bytes_read == size; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - LLDB_LOG(log, - "using process_vm_readv to read {0} bytes from inferior " - "address {1:x}: {2}", - size, addr, success ? "Success" : llvm::sys::StrError(errno)); - - if (success) - return Status(); - // else the call failed for some reason, let's retry the read using ptrace - // api. - } - - unsigned char *dst = static_cast<unsigned char *>(buf); - size_t remainder; - long data; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); - LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); - - for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { - Status error = NativeProcessLinux::PtraceWrapper( - PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data); - if (error.Fail()) - return error; - - remainder = size - bytes_read; - remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; - - // Copy the data into our buffer - memcpy(dst, &data, remainder); - - LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); - addr += k_ptrace_word_size; - dst += k_ptrace_word_size; - } - return Status(); -} - -Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, - size_t size, size_t &bytes_written) { - const unsigned char *src = static_cast<const unsigned char *>(buf); - size_t remainder; - Status error; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); - LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size); - - for (bytes_written = 0; bytes_written < size; bytes_written += remainder) { - remainder = size - bytes_written; - remainder = remainder > k_ptrace_word_size ? k_ptrace_word_size : remainder; - - if (remainder == k_ptrace_word_size) { - unsigned long data = 0; - memcpy(&data, src, k_ptrace_word_size); - - LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data); - error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(), - (void *)addr, (void *)data); - if (error.Fail()) - return error; - } else { - unsigned char buff[8]; - size_t bytes_read; - error = ReadMemory(addr, buff, k_ptrace_word_size, bytes_read); - if (error.Fail()) - return error; - - memcpy(buff, src, remainder); - - size_t bytes_written_rec; - error = WriteMemory(addr, buff, k_ptrace_word_size, bytes_written_rec); - if (error.Fail()) - return error; - - LLDB_LOG(log, "[{0:x}]:{1:x} ({2:x})", addr, *(const unsigned long *)src, - *(unsigned long *)buff); - } - - addr += k_ptrace_word_size; - src += k_ptrace_word_size; - } - return error; -} - -Status NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) { - return PtraceWrapper(PTRACE_GETSIGINFO, tid, nullptr, siginfo); -} - -Status NativeProcessLinux::GetEventMessage(lldb::tid_t tid, - unsigned long *message) { - return PtraceWrapper(PTRACE_GETEVENTMSG, tid, nullptr, message); -} - -Status NativeProcessLinux::Detach(lldb::tid_t tid) { - if (tid == LLDB_INVALID_THREAD_ID) - return Status(); - - return PtraceWrapper(PTRACE_DETACH, tid); -} - -bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { - for (const auto &thread : m_threads) { - assert(thread && "thread list should not contain NULL threads"); - if (thread->GetID() == thread_id) { - // We have this thread. - return true; - } - } - - // We don't have this thread. - return false; -} - -bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { - Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - LLDB_LOG(log, "tid: {0})", thread_id); - - bool found = false; - for (auto it = m_threads.begin(); it != m_threads.end(); ++it) { - if (*it && ((*it)->GetID() == thread_id)) { - m_threads.erase(it); - found = true; - break; - } - } - - if (found) - StopTracingForThread(thread_id); - SignalIfAllThreadsStopped(); - return found; -} - -NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id); - - assert(!HasThreadNoLock(thread_id) && - "attempted to add a thread by id that already exists"); - - // If this is the first thread, save it as the current thread - if (m_threads.empty()) - SetCurrentThreadID(thread_id); - - m_threads.push_back(llvm::make_unique<NativeThreadLinux>(*this, thread_id)); - - if (m_pt_proces_trace_id != LLDB_INVALID_UID) { - auto traceMonitor = ProcessorTraceMonitor::Create( - GetID(), thread_id, m_pt_process_trace_config, true); - if (traceMonitor) { - m_pt_traced_thread_group.insert(thread_id); - m_processor_trace_monitor.insert( - std::make_pair(thread_id, std::move(*traceMonitor))); - } else { - LLDB_LOG(log, "failed to start trace on thread {0}", thread_id); - Status error(traceMonitor.takeError()); - LLDB_LOG(log, "error {0}", error); - } - } - - return static_cast<NativeThreadLinux &>(*m_threads.back()); -} - -Status NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path, - FileSpec &file_spec) { - Status error = PopulateMemoryRegionCache(); - if (error.Fail()) - return error; - - FileSpec module_file_spec(module_path); - FileSystem::Instance().Resolve(module_file_spec); - - file_spec.Clear(); - for (const auto &it : m_mem_region_cache) { - if (it.second.GetFilename() == module_file_spec.GetFilename()) { - file_spec = it.second; - return Status(); - } - } - return Status("Module file (%s) not found in /proc/%" PRIu64 "/maps file!", - module_file_spec.GetFilename().AsCString(), GetID()); -} - -Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name, - lldb::addr_t &load_addr) { - load_addr = LLDB_INVALID_ADDRESS; - Status error = PopulateMemoryRegionCache(); - if (error.Fail()) - return error; - - FileSpec file(file_name); - for (const auto &it : m_mem_region_cache) { - if (it.second == file) { - load_addr = it.first.GetRange().GetRangeBase(); - return Status(); - } - } - return Status("No load address found for specified file."); -} - -NativeThreadLinux *NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { - return static_cast<NativeThreadLinux *>( - NativeProcessProtocol::GetThreadByID(tid)); -} - -Status NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, - lldb::StateType state, int signo) { - Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - LLDB_LOG(log, "tid: {0}", thread.GetID()); - - // Before we do the resume below, first check if we have a pending stop - // notification that is currently waiting for all threads to stop. This is - // potentially a buggy situation since we're ostensibly waiting for threads - // to stop before we send out the pending notification, and here we are - // resuming one before we send out the pending stop notification. - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) { - LLDB_LOG(log, - "about to resume tid {0} per explicit request but we have a " - "pending stop notification (tid {1}) that is actively " - "waiting for this thread to stop. Valid sequence of events?", - thread.GetID(), m_pending_notification_tid); - } - - // Request a resume. We expect this to be synchronous and the system to - // reflect it is running after this completes. - switch (state) { - case eStateRunning: { - const auto resume_result = thread.Resume(signo); - if (resume_result.Success()) - SetState(eStateRunning, true); - return resume_result; - } - case eStateStepping: { - const auto step_result = thread.SingleStep(signo); - if (step_result.Success()) - SetState(eStateRunning, true); - return step_result; - } - default: - LLDB_LOG(log, "Unhandled state {0}.", state); - llvm_unreachable("Unhandled state for resume"); - } -} - -//===----------------------------------------------------------------------===// - -void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) { - Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - LLDB_LOG(log, "about to process event: (triggering_tid: {0})", - triggering_tid); - - m_pending_notification_tid = triggering_tid; - - // Request a stop for all the thread stops that need to be stopped and are - // not already known to be stopped. - for (const auto &thread : m_threads) { - if (StateIsRunningState(thread->GetState())) - static_cast<NativeThreadLinux *>(thread.get())->RequestStop(); - } - - SignalIfAllThreadsStopped(); - LLDB_LOG(log, "event processing done"); -} - -void NativeProcessLinux::SignalIfAllThreadsStopped() { - if (m_pending_notification_tid == LLDB_INVALID_THREAD_ID) - return; // No pending notification. Nothing to do. - - for (const auto &thread_sp : m_threads) { - if (StateIsRunningState(thread_sp->GetState())) - return; // Some threads are still running. Don't signal yet. - } - - // We have a pending notification and all threads have stopped. - Log *log( - GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_BREAKPOINTS)); - - // Clear any temporary breakpoints we used to implement software single - // stepping. - for (const auto &thread_info : m_threads_stepping_with_breakpoint) { - Status error = RemoveBreakpoint(thread_info.second); - if (error.Fail()) - LLDB_LOG(log, "pid = {0} remove stepping breakpoint: {1}", - thread_info.first, error); - } - m_threads_stepping_with_breakpoint.clear(); - - // Notify the delegate about the stop - SetCurrentThreadID(m_pending_notification_tid); - SetState(StateType::eStateStopped, true); - m_pending_notification_tid = LLDB_INVALID_THREAD_ID; -} - -void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) { - Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - LLDB_LOG(log, "tid: {0}", thread.GetID()); - - if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID && - StateIsRunningState(thread.GetState())) { - // We will need to wait for this new thread to stop as well before firing - // the notification. - thread.RequestStop(); - } -} - -void NativeProcessLinux::SigchldHandler() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - // Process all pending waitpid notifications. - while (true) { - int status = -1; - ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, - __WALL | __WNOTHREAD | WNOHANG); - - if (wait_pid == 0) - break; // We are done. - - if (wait_pid == -1) { - Status error(errno, eErrorTypePOSIX); - LLDB_LOG(log, "waitpid (-1, &status, _) failed: {0}", error); - break; - } - - WaitStatus wait_status = WaitStatus::Decode(status); - bool exited = wait_status.type == WaitStatus::Exit || - (wait_status.type == WaitStatus::Signal && - wait_pid == static_cast<::pid_t>(GetID())); - - LLDB_LOG( - log, - "waitpid (-1, &status, _) => pid = {0}, status = {1}, exited = {2}", - wait_pid, wait_status, exited); - - MonitorCallback(wait_pid, exited, wait_status); - } -} - -// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets -// errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) -Status NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, - void *data, size_t data_size, - long *result) { - Status error; - long int ret; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - PtraceDisplayBytes(req, data, data_size); - - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), - *(unsigned int *)addr, data); - else - ret = ptrace(static_cast<__ptrace_request>(req), static_cast<::pid_t>(pid), - addr, data); - - if (ret == -1) - error.SetErrorToErrno(); - - if (result) - *result = ret; - - LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data, - data_size, ret); - - PtraceDisplayBytes(req, data, data_size); - - if (error.Fail()) - LLDB_LOG(log, "ptrace() failed: {0}", error); - - return error; -} - -llvm::Expected<ProcessorTraceMonitor &> -NativeProcessLinux::LookupProcessorTraceInstance(lldb::user_id_t traceid, - lldb::tid_t thread) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - if (thread == LLDB_INVALID_THREAD_ID && traceid == m_pt_proces_trace_id) { - LLDB_LOG(log, "thread not specified: {0}", traceid); - return Status("tracing not active thread not specified").ToError(); - } - - for (auto& iter : m_processor_trace_monitor) { - if (traceid == iter.second->GetTraceID() && - (thread == iter.first || thread == LLDB_INVALID_THREAD_ID)) - return *(iter.second); - } - - LLDB_LOG(log, "traceid not being traced: {0}", traceid); - return Status("tracing not active for this thread").ToError(); -} - -Status NativeProcessLinux::GetMetaData(lldb::user_id_t traceid, - lldb::tid_t thread, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { - TraceOptions trace_options; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - - LLDB_LOG(log, "traceid {0}", traceid); - - auto perf_monitor = LookupProcessorTraceInstance(traceid, thread); - if (!perf_monitor) { - LLDB_LOG(log, "traceid not being traced: {0}", traceid); - buffer = buffer.slice(buffer.size()); - error = perf_monitor.takeError(); - return error; - } - return (*perf_monitor).ReadPerfTraceData(buffer, offset); -} - -Status NativeProcessLinux::GetData(lldb::user_id_t traceid, lldb::tid_t thread, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - - LLDB_LOG(log, "traceid {0}", traceid); - - auto perf_monitor = LookupProcessorTraceInstance(traceid, thread); - if (!perf_monitor) { - LLDB_LOG(log, "traceid not being traced: {0}", traceid); - buffer = buffer.slice(buffer.size()); - error = perf_monitor.takeError(); - return error; - } - return (*perf_monitor).ReadPerfTraceAux(buffer, offset); -} - -Status NativeProcessLinux::GetTraceConfig(lldb::user_id_t traceid, - TraceOptions &config) { - Status error; - if (config.getThreadID() == LLDB_INVALID_THREAD_ID && - m_pt_proces_trace_id == traceid) { - if (m_pt_proces_trace_id == LLDB_INVALID_UID) { - error.SetErrorString("tracing not active for this process"); - return error; - } - config = m_pt_process_trace_config; - } else { - auto perf_monitor = - LookupProcessorTraceInstance(traceid, config.getThreadID()); - if (!perf_monitor) { - error = perf_monitor.takeError(); - return error; - } - error = (*perf_monitor).GetTraceConfig(config); - } - return error; -} - -lldb::user_id_t -NativeProcessLinux::StartTraceGroup(const TraceOptions &config, - Status &error) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - if (config.getType() != TraceType::eTraceTypeProcessorTrace) - return LLDB_INVALID_UID; - - if (m_pt_proces_trace_id != LLDB_INVALID_UID) { - error.SetErrorString("tracing already active on this process"); - return m_pt_proces_trace_id; - } - - for (const auto &thread_sp : m_threads) { - if (auto traceInstance = ProcessorTraceMonitor::Create( - GetID(), thread_sp->GetID(), config, true)) { - m_pt_traced_thread_group.insert(thread_sp->GetID()); - m_processor_trace_monitor.insert( - std::make_pair(thread_sp->GetID(), std::move(*traceInstance))); - } - } - - m_pt_process_trace_config = config; - error = ProcessorTraceMonitor::GetCPUType(m_pt_process_trace_config); - - // Trace on Complete process will have traceid of 0 - m_pt_proces_trace_id = 0; - - LLDB_LOG(log, "Process Trace ID {0}", m_pt_proces_trace_id); - return m_pt_proces_trace_id; -} - -lldb::user_id_t NativeProcessLinux::StartTrace(const TraceOptions &config, - Status &error) { - if (config.getType() != TraceType::eTraceTypeProcessorTrace) - return NativeProcessProtocol::StartTrace(config, error); - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - lldb::tid_t threadid = config.getThreadID(); - - if (threadid == LLDB_INVALID_THREAD_ID) - return StartTraceGroup(config, error); - - auto thread_sp = GetThreadByID(threadid); - if (!thread_sp) { - // Thread not tracked by lldb so don't trace. - error.SetErrorString("invalid thread id"); - return LLDB_INVALID_UID; - } - - const auto &iter = m_processor_trace_monitor.find(threadid); - if (iter != m_processor_trace_monitor.end()) { - LLDB_LOG(log, "Thread already being traced"); - error.SetErrorString("tracing already active on this thread"); - return LLDB_INVALID_UID; - } - - auto traceMonitor = - ProcessorTraceMonitor::Create(GetID(), threadid, config, false); - if (!traceMonitor) { - error = traceMonitor.takeError(); - LLDB_LOG(log, "error {0}", error); - return LLDB_INVALID_UID; - } - lldb::user_id_t ret_trace_id = (*traceMonitor)->GetTraceID(); - m_processor_trace_monitor.insert( - std::make_pair(threadid, std::move(*traceMonitor))); - return ret_trace_id; -} - -Status NativeProcessLinux::StopTracingForThread(lldb::tid_t thread) { - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - LLDB_LOG(log, "Thread {0}", thread); - - const auto& iter = m_processor_trace_monitor.find(thread); - if (iter == m_processor_trace_monitor.end()) { - error.SetErrorString("tracing not active for this thread"); - return error; - } - - if (iter->second->GetTraceID() == m_pt_proces_trace_id) { - // traceid maps to the whole process so we have to erase it from the thread - // group. - LLDB_LOG(log, "traceid maps to process"); - m_pt_traced_thread_group.erase(thread); - } - m_processor_trace_monitor.erase(iter); - - return error; -} - -Status NativeProcessLinux::StopTrace(lldb::user_id_t traceid, - lldb::tid_t thread) { - Status error; - - TraceOptions trace_options; - trace_options.setThreadID(thread); - error = NativeProcessLinux::GetTraceConfig(traceid, trace_options); - - if (error.Fail()) - return error; - - switch (trace_options.getType()) { - case lldb::TraceType::eTraceTypeProcessorTrace: - if (traceid == m_pt_proces_trace_id && - thread == LLDB_INVALID_THREAD_ID) - StopProcessorTracingOnProcess(); - else - error = StopProcessorTracingOnThread(traceid, thread); - break; - default: - error.SetErrorString("trace not supported"); - break; - } - - return error; -} - -void NativeProcessLinux::StopProcessorTracingOnProcess() { - for (auto thread_id_iter : m_pt_traced_thread_group) - m_processor_trace_monitor.erase(thread_id_iter); - m_pt_traced_thread_group.clear(); - m_pt_proces_trace_id = LLDB_INVALID_UID; -} - -Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid, - lldb::tid_t thread) { - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - if (thread == LLDB_INVALID_THREAD_ID) { - for (auto& iter : m_processor_trace_monitor) { - if (iter.second->GetTraceID() == traceid) { - // Stopping a trace instance for an individual thread hence there will - // only be one traceid that can match. - m_processor_trace_monitor.erase(iter.first); - return error; - } - LLDB_LOG(log, "Trace ID {0}", iter.second->GetTraceID()); - } - - LLDB_LOG(log, "Invalid TraceID"); - error.SetErrorString("invalid trace id"); - return error; - } - - // thread is specified so we can use find function on the map. - const auto& iter = m_processor_trace_monitor.find(thread); - if (iter == m_processor_trace_monitor.end()) { - // thread not found in our map. - LLDB_LOG(log, "thread not being traced"); - error.SetErrorString("tracing not active for this thread"); - return error; - } - if (iter->second->GetTraceID() != traceid) { - // traceid did not match so it has to be invalid. - LLDB_LOG(log, "Invalid TraceID"); - error.SetErrorString("invalid trace id"); - return error; - } - - LLDB_LOG(log, "UID - {0} , Thread -{1}", traceid, thread); - - if (traceid == m_pt_proces_trace_id) { - // traceid maps to the whole process so we have to erase it from the thread - // group. - LLDB_LOG(log, "traceid maps to process"); - m_pt_traced_thread_group.erase(thread); - } - m_processor_trace_monitor.erase(iter); - - return error; -} diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h deleted file mode 100644 index 69f2b528d3300..0000000000000 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ /dev/null @@ -1,261 +0,0 @@ -//===-- NativeProcessLinux.h ---------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeProcessLinux_H_ -#define liblldb_NativeProcessLinux_H_ - -#include <csignal> -#include <unordered_set> - -#include "lldb/Host/Debug.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/linux/Support.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/lldb-types.h" - -#include "NativeThreadLinux.h" -#include "ProcessorTrace.h" -#include "lldb/Host/common/NativeProcessProtocol.h" - -namespace lldb_private { -class Status; -class Scalar; - -namespace process_linux { -/// @class NativeProcessLinux -/// Manages communication with the inferior (debugee) process. -/// -/// Upon construction, this class prepares and launches an inferior process -/// for debugging. -/// -/// Changes in the inferior process state are broadcasted. -class NativeProcessLinux : public NativeProcessProtocol { -public: - class Factory : public NativeProcessProtocol::Factory { - public: - llvm::Expected<std::unique_ptr<NativeProcessProtocol>> - Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, - MainLoop &mainloop) const override; - - llvm::Expected<std::unique_ptr<NativeProcessProtocol>> - Attach(lldb::pid_t pid, NativeDelegate &native_delegate, - MainLoop &mainloop) const override; - }; - - // --------------------------------------------------------------------- - // NativeProcessProtocol Interface - // --------------------------------------------------------------------- - Status Resume(const ResumeActionList &resume_actions) override; - - Status Halt() override; - - Status Detach() override; - - Status Signal(int signo) override; - - Status Interrupt() override; - - Status Kill() override; - - Status GetMemoryRegionInfo(lldb::addr_t load_addr, - MemoryRegionInfo &range_info) override; - - Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, - size_t &bytes_read) override; - - Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, - size_t &bytes_written) override; - - Status AllocateMemory(size_t size, uint32_t permissions, - lldb::addr_t &addr) override; - - Status DeallocateMemory(lldb::addr_t addr) override; - - lldb::addr_t GetSharedLibraryInfoAddress() override; - - size_t UpdateThreads() override; - - const ArchSpec &GetArchitecture() const override { return m_arch; } - - Status SetBreakpoint(lldb::addr_t addr, uint32_t size, - bool hardware) override; - - Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override; - - void DoStopIDBumped(uint32_t newBumpId) override; - - Status GetLoadedModuleFileSpec(const char *module_path, - FileSpec &file_spec) override; - - Status GetFileLoadAddress(const llvm::StringRef &file_name, - lldb::addr_t &load_addr) override; - - NativeThreadLinux *GetThreadByID(lldb::tid_t id); - - llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> - GetAuxvData() const override { - return getProcFile(GetID(), "auxv"); - } - - lldb::user_id_t StartTrace(const TraceOptions &config, - Status &error) override; - - Status StopTrace(lldb::user_id_t traceid, - lldb::tid_t thread) override; - - Status GetData(lldb::user_id_t traceid, lldb::tid_t thread, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0) override; - - Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0) override; - - Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) override; - - // --------------------------------------------------------------------- - // Interface used by NativeRegisterContext-derived classes. - // --------------------------------------------------------------------- - static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, - void *data = nullptr, size_t data_size = 0, - long *result = nullptr); - - bool SupportHardwareSingleStepping() const; - -protected: - llvm::Expected<llvm::ArrayRef<uint8_t>> - GetSoftwareBreakpointTrapOpcode(size_t size_hint) override; - -private: - MainLoop::SignalHandleUP m_sigchld_handle; - ArchSpec m_arch; - - LazyBool m_supports_mem_region = eLazyBoolCalculate; - std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; - - lldb::tid_t m_pending_notification_tid = LLDB_INVALID_THREAD_ID; - - // List of thread ids stepping with a breakpoint with the address of - // the relevan breakpoint - std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint; - - // --------------------------------------------------------------------- - // Private Instance Methods - // --------------------------------------------------------------------- - NativeProcessLinux(::pid_t pid, int terminal_fd, NativeDelegate &delegate, - const ArchSpec &arch, MainLoop &mainloop, - llvm::ArrayRef<::pid_t> tids); - - // Returns a list of process threads that we have attached to. - static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid); - - static Status SetDefaultPtraceOpts(const lldb::pid_t); - - void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status); - - void WaitForNewThread(::pid_t tid); - - void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread); - - void MonitorTrace(NativeThreadLinux &thread); - - void MonitorBreakpoint(NativeThreadLinux &thread); - - void MonitorWatchpoint(NativeThreadLinux &thread, uint32_t wp_index); - - void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, - bool exited); - - Status SetupSoftwareSingleStepping(NativeThreadLinux &thread); - - bool HasThreadNoLock(lldb::tid_t thread_id); - - bool StopTrackingThread(lldb::tid_t thread_id); - - NativeThreadLinux &AddThread(lldb::tid_t thread_id); - - /// Writes a siginfo_t structure corresponding to the given thread ID to the - /// memory region pointed to by @p siginfo. - Status GetSignalInfo(lldb::tid_t tid, void *siginfo); - - /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) - /// corresponding to the given thread ID to the memory pointed to by @p - /// message. - Status GetEventMessage(lldb::tid_t tid, unsigned long *message); - - void NotifyThreadDeath(lldb::tid_t tid); - - Status Detach(lldb::tid_t tid); - - // This method is requests a stop on all threads which are still running. It - // sets up a - // deferred delegate notification, which will fire once threads report as - // stopped. The - // triggerring_tid will be set as the current thread (main stop reason). - void StopRunningThreads(lldb::tid_t triggering_tid); - - // Notify the delegate if all threads have stopped. - void SignalIfAllThreadsStopped(); - - // Resume the given thread, optionally passing it the given signal. The type - // of resume - // operation (continue, single-step) depends on the state parameter. - Status ResumeThread(NativeThreadLinux &thread, lldb::StateType state, - int signo); - - void ThreadWasCreated(NativeThreadLinux &thread); - - void SigchldHandler(); - - Status PopulateMemoryRegionCache(); - - lldb::user_id_t StartTraceGroup(const TraceOptions &config, - Status &error); - - // This function is intended to be used to stop tracing - // on a thread that exited. - Status StopTracingForThread(lldb::tid_t thread); - - // The below function as the name suggests, looks up a ProcessorTrace - // instance from the m_processor_trace_monitor map. In the case of - // process tracing where the traceid passed would map to the complete - // process, it is mandatory to provide a threadid to obtain a trace - // instance (since ProcessorTrace is tied to a thread). In the other - // scenario that an individual thread is being traced, just the traceid - // is sufficient to obtain the actual ProcessorTrace instance. - llvm::Expected<ProcessorTraceMonitor &> - LookupProcessorTraceInstance(lldb::user_id_t traceid, lldb::tid_t thread); - - // Stops tracing on individual threads being traced. Not intended - // to be used to stop tracing on complete process. - Status StopProcessorTracingOnThread(lldb::user_id_t traceid, - lldb::tid_t thread); - - // Intended to stop tracing on complete process. - // Should not be used for stopping trace on - // individual threads. - void StopProcessorTracingOnProcess(); - - llvm::DenseMap<lldb::tid_t, ProcessorTraceMonitorUP> - m_processor_trace_monitor; - - // Set for tracking threads being traced under - // same process user id. - llvm::DenseSet<lldb::tid_t> m_pt_traced_thread_group; - - lldb::user_id_t m_pt_proces_trace_id = LLDB_INVALID_UID; - TraceOptions m_pt_process_trace_config; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef liblldb_NativeProcessLinux_H_ diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp deleted file mode 100644 index 79f635c88985b..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ /dev/null @@ -1,196 +0,0 @@ -//===-- NativeRegisterContextLinux.cpp --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "NativeRegisterContextLinux.h" - -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Utility/RegisterValue.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -NativeRegisterContextLinux::NativeRegisterContextLinux( - NativeThreadProtocol &native_thread, - RegisterInfoInterface *reg_info_interface_p) - : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {} - -lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const { - return m_thread.GetProcess().GetByteOrder(); -} - -Status NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, - RegisterValue ®_value) { - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - if (!reg_info) - return Status("register %" PRIu32 " not found", reg_index); - - return DoReadRegisterValue(reg_info->byte_offset, reg_info->name, - reg_info->byte_size, reg_value); -} - -Status -NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, - const RegisterValue ®_value) { - uint32_t reg_to_write = reg_index; - RegisterValue value_to_write = reg_value; - - // Check if this is a subregister of a full register. - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index); - if (reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) { - Status error; - - RegisterValue full_value; - uint32_t full_reg = reg_info->invalidate_regs[0]; - const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg); - - // Read the full register. - error = ReadRegister(full_reg_info, full_value); - if (error.Fail()) - return error; - - lldb::ByteOrder byte_order = GetByteOrder(); - uint8_t dst[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the full register. - const uint32_t dest_size = full_value.GetAsMemoryData( - full_reg_info, dst, sizeof(dst), byte_order, error); - if (error.Success() && dest_size) { - uint8_t src[RegisterValue::kMaxRegisterByteSize]; - - // Get the bytes for the source data. - const uint32_t src_size = reg_value.GetAsMemoryData( - reg_info, src, sizeof(src), byte_order, error); - if (error.Success() && src_size && (src_size < dest_size)) { - // Copy the src bytes to the destination. - memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size); - // Set this full register as the value to write. - value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order); - value_to_write.SetType(full_reg_info); - reg_to_write = full_reg; - } - } - } - - const RegisterInfo *const register_to_write_info_p = - GetRegisterInfoAtIndex(reg_to_write); - assert(register_to_write_info_p && - "register to write does not have valid RegisterInfo"); - if (!register_to_write_info_p) - return Status("NativeRegisterContextLinux::%s failed to get RegisterInfo " - "for write register index %" PRIu32, - __FUNCTION__, reg_to_write); - - return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, reg_value); -} - -Status NativeRegisterContextLinux::ReadGPR() { - void *buf = GetGPRBuffer(); - if (!buf) - return Status("GPR buffer is NULL"); - size_t buf_size = GetGPRSize(); - - return DoReadGPR(buf, buf_size); -} - -Status NativeRegisterContextLinux::WriteGPR() { - void *buf = GetGPRBuffer(); - if (!buf) - return Status("GPR buffer is NULL"); - size_t buf_size = GetGPRSize(); - - return DoWriteGPR(buf, buf_size); -} - -Status NativeRegisterContextLinux::ReadFPR() { - void *buf = GetFPRBuffer(); - if (!buf) - return Status("FPR buffer is NULL"); - size_t buf_size = GetFPRSize(); - - return DoReadFPR(buf, buf_size); -} - -Status NativeRegisterContextLinux::WriteFPR() { - void *buf = GetFPRBuffer(); - if (!buf) - return Status("FPR buffer is NULL"); - size_t buf_size = GetFPRSize(); - - return DoWriteFPR(buf, buf_size); -} - -Status NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, - unsigned int regset) { - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), - static_cast<void *>(®set), buf, - buf_size); -} - -Status NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, - unsigned int regset) { - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), - static_cast<void *>(®set), buf, - buf_size); -} - -Status NativeRegisterContextLinux::DoReadRegisterValue(uint32_t offset, - const char *reg_name, - uint32_t size, - RegisterValue &value) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); - - long data; - Status error = NativeProcessLinux::PtraceWrapper( - PTRACE_PEEKUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), - nullptr, 0, &data); - - if (error.Success()) - // First cast to an unsigned of the same size to avoid sign extension. - value.SetUInt(static_cast<unsigned long>(data), size); - - LLDB_LOG(log, "{0}: {1:x}", reg_name, data); - return error; -} - -Status NativeRegisterContextLinux::DoWriteRegisterValue( - uint32_t offset, const char *reg_name, const RegisterValue &value) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS)); - - void *buf = reinterpret_cast<void *>(value.GetAsUInt64()); - LLDB_LOG(log, "{0}: {1}", reg_name, buf); - - return NativeProcessLinux::PtraceWrapper( - PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(offset), buf); -} - -Status NativeRegisterContextLinux::DoReadGPR(void *buf, size_t buf_size) { - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), - nullptr, buf, buf_size); -} - -Status NativeRegisterContextLinux::DoWriteGPR(void *buf, size_t buf_size) { - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), - nullptr, buf, buf_size); -} - -Status NativeRegisterContextLinux::DoReadFPR(void *buf, size_t buf_size) { - return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), - nullptr, buf, buf_size); -} - -Status NativeRegisterContextLinux::DoWriteFPR(void *buf, size_t buf_size) { - return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), - nullptr, buf, buf_size); -} diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h deleted file mode 100644 index 2cea497b53bcd..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- NativeRegisterContextLinux.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_NativeRegisterContextLinux_h -#define lldb_NativeRegisterContextLinux_h - -#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" -#include "lldb/Host/common/NativeThreadProtocol.h" - -namespace lldb_private { -namespace process_linux { - -class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo { -public: - NativeRegisterContextLinux(NativeThreadProtocol &native_thread, - RegisterInfoInterface *reg_info_interface_p); - - // This function is implemented in the NativeRegisterContextLinux_* subclasses - // to create a new instance of the host specific NativeRegisterContextLinux. - // The implementations can't collide as only one NativeRegisterContextLinux_* - // variant should be compiled into the final executable. - static std::unique_ptr<NativeRegisterContextLinux> - CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - -protected: - lldb::ByteOrder GetByteOrder() const; - - virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value); - - virtual Status WriteRegisterRaw(uint32_t reg_index, - const RegisterValue ®_value); - - virtual Status ReadRegisterSet(void *buf, size_t buf_size, - unsigned int regset); - - virtual Status WriteRegisterSet(void *buf, size_t buf_size, - unsigned int regset); - - virtual Status ReadGPR(); - - virtual Status WriteGPR(); - - virtual Status ReadFPR(); - - virtual Status WriteFPR(); - - virtual void *GetGPRBuffer() { return nullptr; } - - virtual size_t GetGPRSize() { - return GetRegisterInfoInterface().GetGPRSize(); - } - - virtual void *GetFPRBuffer() { return nullptr; } - - virtual size_t GetFPRSize() { return 0; } - - // The Do*** functions are executed on the privileged thread and can perform - // ptrace - // operations directly. - virtual Status DoReadRegisterValue(uint32_t offset, const char *reg_name, - uint32_t size, RegisterValue &value); - - virtual Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value); - - virtual Status DoReadGPR(void *buf, size_t buf_size); - - virtual Status DoWriteGPR(void *buf, size_t buf_size); - - virtual Status DoReadFPR(void *buf, size_t buf_size); - - virtual Status DoWriteFPR(void *buf, size_t buf_size); -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_h diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp deleted file mode 100644 index 09d3a12942f05..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ /dev/null @@ -1,975 +0,0 @@ -//===-- NativeRegisterContextLinux_arm.cpp --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#include "NativeRegisterContextLinux_arm.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" - -#include <elf.h> -#include <sys/socket.h> - -#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr)) - -#ifndef PTRACE_GETVFPREGS -#define PTRACE_GETVFPREGS 27 -#define PTRACE_SETVFPREGS 28 -#endif -#ifndef PTRACE_GETHBPREGS -#define PTRACE_GETHBPREGS 29 -#define PTRACE_SETHBPREGS 30 -#endif -#if !defined(PTRACE_TYPE_ARG3) -#define PTRACE_TYPE_ARG3 void * -#endif -#if !defined(PTRACE_TYPE_ARG4) -#define PTRACE_TYPE_ARG4 void * -#endif - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -// arm general purpose registers. -static const uint32_t g_gpr_regnums_arm[] = { - gpr_r0_arm, gpr_r1_arm, gpr_r2_arm, gpr_r3_arm, gpr_r4_arm, - gpr_r5_arm, gpr_r6_arm, gpr_r7_arm, gpr_r8_arm, gpr_r9_arm, - gpr_r10_arm, gpr_r11_arm, gpr_r12_arm, gpr_sp_arm, gpr_lr_arm, - gpr_pc_arm, gpr_cpsr_arm, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) == - k_num_gpr_registers_arm, - "g_gpr_regnums_arm has wrong number of register infos"); - -// arm floating point registers. -static const uint32_t g_fpu_regnums_arm[] = { - fpu_s0_arm, fpu_s1_arm, fpu_s2_arm, fpu_s3_arm, fpu_s4_arm, - fpu_s5_arm, fpu_s6_arm, fpu_s7_arm, fpu_s8_arm, fpu_s9_arm, - fpu_s10_arm, fpu_s11_arm, fpu_s12_arm, fpu_s13_arm, fpu_s14_arm, - fpu_s15_arm, fpu_s16_arm, fpu_s17_arm, fpu_s18_arm, fpu_s19_arm, - fpu_s20_arm, fpu_s21_arm, fpu_s22_arm, fpu_s23_arm, fpu_s24_arm, - fpu_s25_arm, fpu_s26_arm, fpu_s27_arm, fpu_s28_arm, fpu_s29_arm, - fpu_s30_arm, fpu_s31_arm, fpu_fpscr_arm, fpu_d0_arm, fpu_d1_arm, - fpu_d2_arm, fpu_d3_arm, fpu_d4_arm, fpu_d5_arm, fpu_d6_arm, - fpu_d7_arm, fpu_d8_arm, fpu_d9_arm, fpu_d10_arm, fpu_d11_arm, - fpu_d12_arm, fpu_d13_arm, fpu_d14_arm, fpu_d15_arm, fpu_d16_arm, - fpu_d17_arm, fpu_d18_arm, fpu_d19_arm, fpu_d20_arm, fpu_d21_arm, - fpu_d22_arm, fpu_d23_arm, fpu_d24_arm, fpu_d25_arm, fpu_d26_arm, - fpu_d27_arm, fpu_d28_arm, fpu_d29_arm, fpu_d30_arm, fpu_d31_arm, - fpu_q0_arm, fpu_q1_arm, fpu_q2_arm, fpu_q3_arm, fpu_q4_arm, - fpu_q5_arm, fpu_q6_arm, fpu_q7_arm, fpu_q8_arm, fpu_q9_arm, - fpu_q10_arm, fpu_q11_arm, fpu_q12_arm, fpu_q13_arm, fpu_q14_arm, - fpu_q15_arm, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) == - k_num_fpr_registers_arm, - "g_fpu_regnums_arm has wrong number of register infos"); - -namespace { -// Number of register sets provided by this context. -enum { k_num_register_sets = 2 }; -} - -// Register sets for arm. -static const RegisterSet g_reg_sets_arm[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_arm, - g_gpr_regnums_arm}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_arm, - g_fpu_regnums_arm}}; - -#if defined(__arm__) - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - return llvm::make_unique<NativeRegisterContextLinux_arm>(target_arch, - native_thread); -} - -#endif // defined(__arm__) - -NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - new RegisterInfoPOSIX_arm(target_arch)) { - switch (target_arch.GetMachine()) { - case llvm::Triple::arm: - m_reg_info.num_registers = k_num_registers_arm; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm; - m_reg_info.last_gpr = k_last_gpr_arm; - m_reg_info.first_fpr = k_first_fpr_arm; - m_reg_info.last_fpr = k_last_fpr_arm; - m_reg_info.first_fpr_v = fpu_s0_arm; - m_reg_info.last_fpr_v = fpu_s31_arm; - m_reg_info.gpr_flags = gpr_cpsr_arm; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - ::memset(&m_fpr, 0, sizeof(m_fpr)); - ::memset(&m_gpr_arm, 0, sizeof(m_gpr_arm)); - ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); - ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); - - // 16 is just a maximum value, query hardware for actual watchpoint count - m_max_hwp_supported = 16; - m_max_hbp_supported = 16; - m_refresh_hwdebug_info = true; -} - -uint32_t NativeRegisterContextLinux_arm::GetRegisterSetCount() const { - return k_num_register_sets; -} - -uint32_t NativeRegisterContextLinux_arm::GetUserRegisterCount() const { - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - count += g_reg_sets_arm[set_index].num_registers; - return count; -} - -const RegisterSet * -NativeRegisterContextLinux_arm::GetRegisterSet(uint32_t set_index) const { - if (set_index < k_num_register_sets) - return &g_reg_sets_arm[set_index]; - - return nullptr; -} - -Status -NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (IsFPR(reg)) { - error = ReadFPR(); - if (error.Fail()) - return error; - } else { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - error = ReadRegisterRaw(full_reg, reg_value); - - if (error.Success()) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned - // value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - - // If our return byte size was greater than the return value reg size, - // then use the type specified by reg_info rather than the uint64_t - // default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; - } - - // Get pointer to m_fpr variable and set the data from it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) { - case 2: - reg_value.SetUInt16(*(uint16_t *)src); - break; - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - case 16: - reg_value.SetBytes(src, 16, GetByteOrder()); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, - reg_info->byte_size); - break; - } - - return error; -} - -Status -NativeRegisterContextLinux_arm::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) { - if (!reg_info) - return Status("reg_info NULL"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name - ? reg_info->name - : "<unknown register>"); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index)) { - // Get pointer to m_fpr variable and set the data to it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < sizeof m_fpr); - uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) { - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled register data size %" PRIu32, - reg_info->byte_size); - } - - Status error = WriteFPR(); - if (error.Fail()) - return error; - - return Status(); - } - - return Status("failed - register wasn't recognized to be a GPR or an FPR, " - "write strategy unknown"); -} - -Status NativeRegisterContextLinux_arm::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) - return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, - (uint64_t)REG_CONTEXT_SIZE); - - error = ReadGPR(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - (uint64_t)REG_CONTEXT_SIZE); - return error; - } - - ::memcpy(dst, &m_gpr_arm, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy(dst, &m_fpr, sizeof(m_fpr)); - - return error; -} - -Status NativeRegisterContextLinux_arm::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, (uint64_t)REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - ::memcpy(&m_gpr_arm, src, GetRegisterInfoInterface().GetGPRSize()); - - error = WriteGPR(); - if (error.Fail()) - return error; - - src += GetRegisterInfoInterface().GetGPRSize(); - ::memcpy(&m_fpr, src, sizeof(m_fpr)); - - error = WriteFPR(); - if (error.Fail()) - return error; - - return error; -} - -bool NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const { - return reg <= m_reg_info.last_gpr; // GPR's come first. -} - -bool NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const { - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); -} - -uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareBreakpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Status error; - - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return 0; - - LLDB_LOG(log, "{0}", m_max_hbp_supported); - return m_max_hbp_supported; -} - -uint32_t -NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, bp_index = 0; - - // Setup address and control values. - // Use size to get a hint of arm vs thumb modes. - switch (size) { - case 2: - control_value = (0x3 << 5) | 7; - addr &= ~1; - break; - case 4: - control_value = (0xfu << 5) | 7; - addr &= ~3; - break; - default: - return LLDB_INVALID_INDEX32; - } - - // Iterate over stored breakpoints and find a free bp_index - bp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hbp_supported; i++) { - if ((m_hbr_regs[i].control & 1) == 0) { - bp_index = i; // Mark last free slot - } else if (m_hbr_regs[i].address == addr) { - return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. - } - } - - if (bp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Update breakpoint in local cache - m_hbr_regs[bp_index].real_addr = addr; - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index); - - if (error.Fail()) { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - - return LLDB_INVALID_INDEX32; - } - - return bp_index; -} - -bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - LLDB_LOG(log, "hw_idx: {0}", hw_idx); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return false; - - if (hw_idx >= m_max_hbp_supported) - return false; - - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - - // PTRACE call to clear corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx); - - if (error.Fail()) { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - - return false; - } - - return true; -} - -Status NativeRegisterContextLinux_arm::GetHardwareBreakHitIndex( - uint32_t &bp_index, lldb::addr_t trap_addr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - lldb::addr_t break_addr; - - for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { - break_addr = m_hbr_regs[bp_index].address; - - if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { - m_hbr_regs[bp_index].hit_addr = trap_addr; - return Status(); - } - } - - bp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -Status NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); - - Status error; - - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return error; - - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0; - - for (uint32_t i = 0; i < m_max_hbp_supported; i++) { - if (m_hbr_regs[i].control & 0x01) { - // Create a backup we can revert to in case of failure. - tempAddr = m_hbr_regs[i].address; - tempControl = m_hbr_regs[i].control; - - // Clear breakpoints in local cache - m_hbr_regs[i].control &= ~1; - m_hbr_regs[i].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeBREAK, i); - - if (error.Fail()) { - m_hbr_regs[i].control = tempControl; - m_hbr_regs[i].address = tempAddr; - - return error; - } - } - } - - return Status(); -} - -uint32_t NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return 0; - - LLDB_LOG(log, "{0}", m_max_hwp_supported); - return m_max_hwp_supported; -} - -uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, - watch_flags); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; - lldb::addr_t real_addr = addr; - - // Check if we are setting watchpoint other than read/write/access Also - // update watchpoint flag to match Arm write-read bit configuration. - switch (watch_flags) { - case 1: - watch_flags = 2; - break; - case 2: - watch_flags = 1; - break; - case 3: - break; - default: - return LLDB_INVALID_INDEX32; - } - - // Can't watch zero bytes - // Can't watch more than 4 bytes per WVR/WCR pair - - if (size == 0 || size > 4) - return LLDB_INVALID_INDEX32; - - // Check 4-byte alignment for hardware watchpoint target address. Below is a - // hack to recalculate address and size in order to make sure we can watch - // non 4-byte alligned addresses as well. - if (addr & 0x03) { - uint8_t watch_mask = (addr & 0x03) + size; - - if (watch_mask > 0x04) - return LLDB_INVALID_INDEX32; - else if (watch_mask <= 0x02) - size = 2; - else if (watch_mask <= 0x04) - size = 4; - - addr = addr & (~0x03); - } - - // We can only watch up to four bytes that follow a 4 byte aligned address - // per watchpoint register pair, so make sure we can properly encode this. - addr_word_offset = addr % 4; - byte_mask = ((1u << size) - 1u) << addr_word_offset; - - // Check if we need multiple watchpoint register - if (byte_mask > 0xfu) - return LLDB_INVALID_INDEX32; - - // Setup control value - // Make the byte_mask into a valid Byte Address Select mask - control_value = byte_mask << 5; - - // Turn on appropriate watchpoint flags read or write - control_value |= (watch_flags << 3); - - // Enable this watchpoint and make it stop in privileged or user mode; - control_value |= 7; - - // Make sure bits 1:0 are clear in our address - addr &= ~((lldb::addr_t)3); - - // Iterate over stored watchpoints and find a free wp_index - wp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - if ((m_hwp_regs[i].control & 1) == 0) { - wp_index = i; // Mark last free slot - } else if (m_hwp_regs[i].address == addr) { - return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. - } - } - - if (wp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].real_addr = real_addr; - m_hwp_regs[wp_index].address = addr; - m_hwp_regs[wp_index].control = control_value; - - // PTRACE call to set corresponding watchpoint register. - error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); - - if (error.Fail()) { - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].control &= ~1; - - return LLDB_INVALID_INDEX32; - } - - return wp_index; -} - -bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint( - uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return false; - - if (wp_index >= m_max_hwp_supported) - return false; - - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; - uint32_t tempControl = m_hwp_regs[wp_index].control; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index); - - if (error.Fail()) { - m_hwp_regs[wp_index].control = tempControl; - m_hwp_regs[wp_index].address = tempAddr; - - return false; - } - - return true; -} - -Status NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() { - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return error; - - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0; - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - if (m_hwp_regs[i].control & 0x01) { - // Create a backup we can revert to in case of failure. - tempAddr = m_hwp_regs[i].address; - tempControl = m_hwp_regs[i].control; - - // Clear watchpoints in local cache - m_hwp_regs[i].control &= ~1; - m_hwp_regs[i].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH, i); - - if (error.Fail()) { - m_hwp_regs[i].control = tempControl; - m_hwp_regs[i].address = tempAddr; - - return error; - } - } - } - - return Status(); -} - -uint32_t NativeRegisterContextLinux_arm::GetWatchpointSize(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) { - case 0x01: - return 1; - case 0x03: - return 2; - case 0x07: - return 3; - case 0x0f: - return 4; - default: - return 0; - } -} -bool NativeRegisterContextLinux_arm::WatchpointIsEnabled(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) - return true; - else - return false; -} - -Status -NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); - - uint32_t watch_size; - lldb::addr_t watch_addr; - - for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { - watch_size = GetWatchpointSize(wp_index); - watch_addr = m_hwp_regs[wp_index].address; - - if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && - trap_addr < watch_addr + watch_size) { - m_hwp_regs[wp_index].hit_addr = trap_addr; - return Status(); - } - } - - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -lldb::addr_t -NativeRegisterContextLinux_arm::GetWatchpointAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].real_addr; - else - return LLDB_INVALID_ADDRESS; -} - -lldb::addr_t -NativeRegisterContextLinux_arm::GetWatchpointHitAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].hit_addr; - else - return LLDB_INVALID_ADDRESS; -} - -Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() { - Status error; - - if (!m_refresh_hwdebug_info) { - return Status(); - } - - unsigned int cap_val; - - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(), - nullptr, &cap_val, - sizeof(unsigned int)); - - if (error.Fail()) - return error; - - m_max_hwp_supported = (cap_val >> 8) & 0xff; - m_max_hbp_supported = cap_val & 0xff; - m_refresh_hwdebug_info = false; - - return error; -} - -Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, - int hwb_index) { - Status error; - - lldb::addr_t *addr_buf; - uint32_t *ctrl_buf; - - if (hwbType == eDREGTypeWATCH) { - addr_buf = &m_hwp_regs[hwb_index].address; - ctrl_buf = &m_hwp_regs[hwb_index].control; - - error = NativeProcessLinux::PtraceWrapper( - PTRACE_SETHBPREGS, m_thread.GetID(), - (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 1), addr_buf, - sizeof(unsigned int)); - - if (error.Fail()) - return error; - - error = NativeProcessLinux::PtraceWrapper( - PTRACE_SETHBPREGS, m_thread.GetID(), - (PTRACE_TYPE_ARG3)(intptr_t) - ((hwb_index << 1) + 2), ctrl_buf, - sizeof(unsigned int)); - } else { - addr_buf = &m_hbr_regs[hwb_index].address; - ctrl_buf = &m_hbr_regs[hwb_index].control; - - error = NativeProcessLinux::PtraceWrapper( - PTRACE_SETHBPREGS, m_thread.GetID(), - (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 1), addr_buf, - sizeof(unsigned int)); - - if (error.Fail()) - return error; - - error = NativeProcessLinux::PtraceWrapper( - PTRACE_SETHBPREGS, m_thread.GetID(), - (PTRACE_TYPE_ARG3)(intptr_t)((hwb_index << 1) + 2), ctrl_buf, - sizeof(unsigned int)); - } - - return error; -} - -uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset( - const RegisterInfo *reg_info) const { - return reg_info->byte_offset - - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; -} - -Status NativeRegisterContextLinux_arm::DoReadRegisterValue( - uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) { - // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android - // devices (always return "Bad address"). To avoid using PTRACE_PEEKUSER we - // read out the full GPR register set instead. This approach is about 4 times - // slower but the performance overhead is negligible in comparision to - // processing time in lldb-server. - assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); - if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) - return Status("Register isn't fit into the size of the GPR area"); - - Status error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); - if (error.Fail()) - return error; - - value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]); - return Status(); -} - -Status NativeRegisterContextLinux_arm::DoWriteRegisterValue( - uint32_t offset, const char *reg_name, const RegisterValue &value) { - // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android - // devices (always return "Bad address"). To avoid using PTRACE_POKEUSER we - // read out the full GPR register set, modify the requested register and - // write it back. This approach is about 4 times slower but the performance - // overhead is negligible in comparision to processing time in lldb-server. - assert(offset % 4 == 0 && "Try to write a register with unaligned offset"); - if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm)) - return Status("Register isn't fit into the size of the GPR area"); - - Status error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm)); - if (error.Fail()) - return error; - - uint32_t reg_value = value.GetAsUInt32(); - // As precaution for an undefined behavior encountered while setting PC we - // will clear thumb bit of new PC if we are already in thumb mode; that is - // CPSR thumb mode bit is set. - if (offset / sizeof(uint32_t) == gpr_pc_arm) { - // Check if we are already in thumb mode and thumb bit of current PC is - // read out to be zero and thumb bit of next PC is read out to be one. - if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && !(m_gpr_arm[gpr_pc_arm] & 0x01) && - (value.GetAsUInt32() & 0x01)) { - reg_value &= (~1ull); - } - } - - m_gpr_arm[offset / sizeof(uint32_t)] = reg_value; - return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm)); -} - -Status NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size) { -#ifdef __arm__ - return NativeRegisterContextLinux::DoReadGPR(buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS); -#endif // __arm__ -} - -Status NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size) { -#ifdef __arm__ - return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS); -#endif // __arm__ -} - -Status NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size) { -#ifdef __arm__ - return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS, m_thread.GetID(), - nullptr, buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP); -#endif // __arm__ -} - -Status NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size) { -#ifdef __arm__ - return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS, m_thread.GetID(), - nullptr, buf, buf_size); -#else // __aarch64__ - struct iovec ioVec; - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - - return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP); -#endif // __arm__ -} - -#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h deleted file mode 100644 index d0b068550a9ee..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ /dev/null @@ -1,169 +0,0 @@ -//===-- NativeRegisterContextLinux_arm.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) - -#ifndef lldb_NativeRegisterContextLinux_arm_h -#define lldb_NativeRegisterContextLinux_arm_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/lldb-arm-register-enums.h" - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_arm(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - uint32_t GetUserRegisterCount() const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - //------------------------------------------------------------------ - // Hardware breakpoints/watchpoint management functions - //------------------------------------------------------------------ - - uint32_t NumSupportedHardwareBreakpoints() override; - - uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - - bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - - Status ClearAllHardwareBreakpoints() override; - - Status GetHardwareBreakHitIndex(uint32_t &bp_index, - lldb::addr_t trap_addr) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - Status ClearAllHardwareWatchpoints() override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t GetWatchpointSize(uint32_t wp_index); - - bool WatchpointIsEnabled(uint32_t wp_index); - - // Debug register type select - enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK }; - -protected: - Status DoReadRegisterValue(uint32_t offset, const char *reg_name, - uint32_t size, RegisterValue &value) override; - - Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value) override; - - Status DoReadGPR(void *buf, size_t buf_size) override; - - Status DoWriteGPR(void *buf, size_t buf_size) override; - - Status DoReadFPR(void *buf, size_t buf_size) override; - - Status DoWriteFPR(void *buf, size_t buf_size) override; - - void *GetGPRBuffer() override { return &m_gpr_arm; } - - void *GetFPRBuffer() override { return &m_fpr; } - - size_t GetFPRSize() override { return sizeof(m_fpr); } - -private: - struct RegInfo { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - - uint32_t first_fpr_v; - uint32_t last_fpr_v; - - uint32_t gpr_flags; - }; - - struct QReg { - uint8_t bytes[16]; - }; - - struct FPU { - union { - uint32_t s[32]; - uint64_t d[32]; - QReg q[16]; // the 128-bit NEON registers - } floats; - uint32_t fpscr; - }; - - uint32_t m_gpr_arm[k_num_gpr_registers_arm]; - RegInfo m_reg_info; - FPU m_fpr; - - // Debug register info for hardware breakpoints and watchpoints management. - struct DREG { - lldb::addr_t address; // Breakpoint/watchpoint address value. - lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception - // occurred. - lldb::addr_t real_addr; // Address value that should cause target to stop. - uint32_t control; // Breakpoint/watchpoint control value. - uint32_t refcount; // Serves as enable/disable and reference counter. - }; - - struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints - struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints - - uint32_t m_max_hwp_supported; - uint32_t m_max_hbp_supported; - bool m_refresh_hwdebug_info; - - bool IsGPR(unsigned reg) const; - - bool IsFPR(unsigned reg) const; - - Status ReadHardwareDebugInfo(); - - Status WriteHardwareDebugRegs(int hwbType, int hwb_index); - - uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h - -#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp deleted file mode 100644 index 9a392edbe9ef3..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ /dev/null @@ -1,985 +0,0 @@ -//===-- NativeRegisterContextLinux_arm64.cpp --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm64__) || defined(__aarch64__) - -#include "NativeRegisterContextLinux_arm.h" -#include "NativeRegisterContextLinux_arm64.h" - - -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" - -// System includes - They have to be included after framework includes because -// they define some macros which collide with variable names in other modules -#include <sys/socket.h> -// NT_PRSTATUS and NT_FPREGSET definition -#include <elf.h> -// user_hwdebug_state definition -#include <asm/ptrace.h> - -#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -// ARM64 general purpose registers. -static const uint32_t g_gpr_regnums_arm64[] = { - gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64, - gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64, - gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64, - gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64, - gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64, - gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64, - gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64, - gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64, - gpr_pc_arm64, gpr_cpsr_arm64, gpr_w0_arm64, gpr_w1_arm64, - gpr_w2_arm64, gpr_w3_arm64, gpr_w4_arm64, gpr_w5_arm64, - gpr_w6_arm64, gpr_w7_arm64, gpr_w8_arm64, gpr_w9_arm64, - gpr_w10_arm64, gpr_w11_arm64, gpr_w12_arm64, gpr_w13_arm64, - gpr_w14_arm64, gpr_w15_arm64, gpr_w16_arm64, gpr_w17_arm64, - gpr_w18_arm64, gpr_w19_arm64, gpr_w20_arm64, gpr_w21_arm64, - gpr_w22_arm64, gpr_w23_arm64, gpr_w24_arm64, gpr_w25_arm64, - gpr_w26_arm64, gpr_w27_arm64, gpr_w28_arm64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) - - 1) == k_num_gpr_registers_arm64, - "g_gpr_regnums_arm64 has wrong number of register infos"); - -// ARM64 floating point registers. -static const uint32_t g_fpu_regnums_arm64[] = { - fpu_v0_arm64, fpu_v1_arm64, fpu_v2_arm64, fpu_v3_arm64, - fpu_v4_arm64, fpu_v5_arm64, fpu_v6_arm64, fpu_v7_arm64, - fpu_v8_arm64, fpu_v9_arm64, fpu_v10_arm64, fpu_v11_arm64, - fpu_v12_arm64, fpu_v13_arm64, fpu_v14_arm64, fpu_v15_arm64, - fpu_v16_arm64, fpu_v17_arm64, fpu_v18_arm64, fpu_v19_arm64, - fpu_v20_arm64, fpu_v21_arm64, fpu_v22_arm64, fpu_v23_arm64, - fpu_v24_arm64, fpu_v25_arm64, fpu_v26_arm64, fpu_v27_arm64, - fpu_v28_arm64, fpu_v29_arm64, fpu_v30_arm64, fpu_v31_arm64, - fpu_s0_arm64, fpu_s1_arm64, fpu_s2_arm64, fpu_s3_arm64, - fpu_s4_arm64, fpu_s5_arm64, fpu_s6_arm64, fpu_s7_arm64, - fpu_s8_arm64, fpu_s9_arm64, fpu_s10_arm64, fpu_s11_arm64, - fpu_s12_arm64, fpu_s13_arm64, fpu_s14_arm64, fpu_s15_arm64, - fpu_s16_arm64, fpu_s17_arm64, fpu_s18_arm64, fpu_s19_arm64, - fpu_s20_arm64, fpu_s21_arm64, fpu_s22_arm64, fpu_s23_arm64, - fpu_s24_arm64, fpu_s25_arm64, fpu_s26_arm64, fpu_s27_arm64, - fpu_s28_arm64, fpu_s29_arm64, fpu_s30_arm64, fpu_s31_arm64, - - fpu_d0_arm64, fpu_d1_arm64, fpu_d2_arm64, fpu_d3_arm64, - fpu_d4_arm64, fpu_d5_arm64, fpu_d6_arm64, fpu_d7_arm64, - fpu_d8_arm64, fpu_d9_arm64, fpu_d10_arm64, fpu_d11_arm64, - fpu_d12_arm64, fpu_d13_arm64, fpu_d14_arm64, fpu_d15_arm64, - fpu_d16_arm64, fpu_d17_arm64, fpu_d18_arm64, fpu_d19_arm64, - fpu_d20_arm64, fpu_d21_arm64, fpu_d22_arm64, fpu_d23_arm64, - fpu_d24_arm64, fpu_d25_arm64, fpu_d26_arm64, fpu_d27_arm64, - fpu_d28_arm64, fpu_d29_arm64, fpu_d30_arm64, fpu_d31_arm64, - fpu_fpsr_arm64, fpu_fpcr_arm64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) - - 1) == k_num_fpr_registers_arm64, - "g_fpu_regnums_arm64 has wrong number of register infos"); - -namespace { -// Number of register sets provided by this context. -enum { k_num_register_sets = 2 }; -} - -// Register sets for ARM64. -static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64, - g_gpr_regnums_arm64}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, - g_fpu_regnums_arm64}}; - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - switch (target_arch.GetMachine()) { - case llvm::Triple::arm: - return llvm::make_unique<NativeRegisterContextLinux_arm>(target_arch, - native_thread); - case llvm::Triple::aarch64: - return llvm::make_unique<NativeRegisterContextLinux_arm64>(target_arch, - native_thread); - default: - llvm_unreachable("have no register context for architecture"); - } -} - -NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - new RegisterInfoPOSIX_arm64(target_arch)) { - switch (target_arch.GetMachine()) { - case llvm::Triple::aarch64: - m_reg_info.num_registers = k_num_registers_arm64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; - m_reg_info.last_gpr = k_last_gpr_arm64; - m_reg_info.first_fpr = k_first_fpr_arm64; - m_reg_info.last_fpr = k_last_fpr_arm64; - m_reg_info.first_fpr_v = fpu_v0_arm64; - m_reg_info.last_fpr_v = fpu_v31_arm64; - m_reg_info.gpr_flags = gpr_cpsr_arm64; - break; - default: - llvm_unreachable("Unhandled target architecture."); - break; - } - - ::memset(&m_fpr, 0, sizeof(m_fpr)); - ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); - ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); - ::memset(&m_hbr_regs, 0, sizeof(m_hbr_regs)); - - // 16 is just a maximum value, query hardware for actual watchpoint count - m_max_hwp_supported = 16; - m_max_hbp_supported = 16; - m_refresh_hwdebug_info = true; -} - -uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { - return k_num_register_sets; -} - -const RegisterSet * -NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { - if (set_index < k_num_register_sets) - return &g_reg_sets_arm64[set_index]; - - return nullptr; -} - -uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - count += g_reg_sets_arm64[set_index].num_registers; - return count; -} - -Status -NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (IsFPR(reg)) { - error = ReadFPR(); - if (error.Fail()) - return error; - } else { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - error = ReadRegisterRaw(full_reg, reg_value); - - if (error.Success()) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned - // value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - - // If our return byte size was greater than the return value reg size, - // then use the type specified by reg_info rather than the uint64_t - // default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; - } - - // Get pointer to m_fpr variable and set the data from it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < sizeof m_fpr); - uint8_t *src = (uint8_t *)&m_fpr + fpr_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, - eByteOrderLittle, error); - - return error; -} - -Status NativeRegisterContextLinux_arm64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - if (!reg_info) - return Status("reg_info NULL"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name - ? reg_info->name - : "<unknown register>"); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index)) { - // Get pointer to m_fpr variable and set the data to it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < sizeof m_fpr); - uint8_t *dst = (uint8_t *)&m_fpr + fpr_offset; - switch (reg_info->byte_size) { - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled register data size %" PRIu32, - reg_info->byte_size); - } - - Status error = WriteFPR(); - if (error.Fail()) - return error; - - return Status(); - } - - return Status("failed - register wasn't recognized to be a GPR or an FPR, " - "write strategy unknown"); -} - -Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) - return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - - error = ReadGPR(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - - ::memcpy(dst, &m_gpr_arm64, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy(dst, &m_fpr, sizeof(m_fpr)); - - return error; -} - -Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - ::memcpy(&m_gpr_arm64, src, GetRegisterInfoInterface().GetGPRSize()); - - error = WriteGPR(); - if (error.Fail()) - return error; - - src += GetRegisterInfoInterface().GetGPRSize(); - ::memcpy(&m_fpr, src, sizeof(m_fpr)); - - error = WriteFPR(); - if (error.Fail()) - return error; - - return error; -} - -bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const { - return reg <= m_reg_info.last_gpr; // GPR's come first. -} - -bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { - return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); -} - -uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Status error; - - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return 0; - - return m_max_hbp_supported; -} - -uint32_t -NativeRegisterContextLinux_arm64::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, bp_index = 0; - - // Check if size has a valid hardware breakpoint length. - if (size != 4) - return LLDB_INVALID_INDEX32; // Invalid size for a AArch64 hardware - // breakpoint - - // Check 4-byte alignment for hardware breakpoint target address. - if (addr & 0x03) - return LLDB_INVALID_INDEX32; // Invalid address, should be 4-byte aligned. - - // Setup control value - control_value = 0; - control_value |= ((1 << size) - 1) << 5; - control_value |= (2 << 1) | 1; - - // Iterate over stored breakpoints and find a free bp_index - bp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hbp_supported; i++) { - if ((m_hbr_regs[i].control & 1) == 0) { - bp_index = i; // Mark last free slot - } else if (m_hbr_regs[i].address == addr) { - return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. - } - } - - if (bp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Update breakpoint in local cache - m_hbr_regs[bp_index].real_addr = addr; - m_hbr_regs[bp_index].address = addr; - m_hbr_regs[bp_index].control = control_value; - - // PTRACE call to set corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK); - - if (error.Fail()) { - m_hbr_regs[bp_index].address = 0; - m_hbr_regs[bp_index].control &= ~1; - - return LLDB_INVALID_INDEX32; - } - - return bp_index; -} - -bool NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint( - uint32_t hw_idx) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - LLDB_LOG(log, "hw_idx: {0}", hw_idx); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return false; - - if (hw_idx >= m_max_hbp_supported) - return false; - - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; - uint32_t tempControl = m_hbr_regs[hw_idx].control; - - m_hbr_regs[hw_idx].control &= ~1; - m_hbr_regs[hw_idx].address = 0; - - // PTRACE call to clear corresponding hardware breakpoint register. - error = WriteHardwareDebugRegs(eDREGTypeBREAK); - - if (error.Fail()) { - m_hbr_regs[hw_idx].control = tempControl; - m_hbr_regs[hw_idx].address = tempAddr; - - return false; - } - - return true; -} - -Status NativeRegisterContextLinux_arm64::GetHardwareBreakHitIndex( - uint32_t &bp_index, lldb::addr_t trap_addr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - lldb::addr_t break_addr; - - for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { - break_addr = m_hbr_regs[bp_index].address; - - if ((m_hbr_regs[bp_index].control & 0x1) && (trap_addr == break_addr)) { - m_hbr_regs[bp_index].hit_addr = trap_addr; - return Status(); - } - } - - bp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -Status NativeRegisterContextLinux_arm64::ClearAllHardwareBreakpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - - if (log) - log->Printf("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); - - Status error; - - // Read hardware breakpoint and watchpoint information. - error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return error; - - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0; - - for (uint32_t i = 0; i < m_max_hbp_supported; i++) { - if (m_hbr_regs[i].control & 0x01) { - // Create a backup we can revert to in case of failure. - tempAddr = m_hbr_regs[i].address; - tempControl = m_hbr_regs[i].control; - - // Clear watchpoints in local cache - m_hbr_regs[i].control &= ~1; - m_hbr_regs[i].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeBREAK); - - if (error.Fail()) { - m_hbr_regs[i].control = tempControl; - m_hbr_regs[i].address = tempAddr; - - return error; - } - } - } - - return Status(); -} - -uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return 0; - - LLDB_LOG(log, "{0}", m_max_hwp_supported); - return m_max_hwp_supported; -} - -uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, - watch_flags); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, wp_index = 0; - lldb::addr_t real_addr = addr; - - // Check if we are setting watchpoint other than read/write/access Also - // update watchpoint flag to match AArch64 write-read bit configuration. - switch (watch_flags) { - case 1: - watch_flags = 2; - break; - case 2: - watch_flags = 1; - break; - case 3: - break; - default: - return LLDB_INVALID_INDEX32; - } - - // Check if size has a valid hardware watchpoint length. - if (size != 1 && size != 2 && size != 4 && size != 8) - return LLDB_INVALID_INDEX32; - - // Check 8-byte alignment for hardware watchpoint target address. Below is a - // hack to recalculate address and size in order to make sure we can watch - // non 8-byte alligned addresses as well. - if (addr & 0x07) { - uint8_t watch_mask = (addr & 0x07) + size; - - if (watch_mask > 0x08) - return LLDB_INVALID_INDEX32; - else if (watch_mask <= 0x02) - size = 2; - else if (watch_mask <= 0x04) - size = 4; - else - size = 8; - - addr = addr & (~0x07); - } - - // Setup control value - control_value = watch_flags << 3; - control_value |= ((1 << size) - 1) << 5; - control_value |= (2 << 1) | 1; - - // Iterate over stored watchpoints and find a free wp_index - wp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - if ((m_hwp_regs[i].control & 1) == 0) { - wp_index = i; // Mark last free slot - } else if (m_hwp_regs[i].address == addr) { - return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. - } - } - - if (wp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].real_addr = real_addr; - m_hwp_regs[wp_index].address = addr; - m_hwp_regs[wp_index].control = control_value; - - // PTRACE call to set corresponding watchpoint register. - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) { - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].control &= ~1; - - return LLDB_INVALID_INDEX32; - } - - return wp_index; -} - -bool NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint( - uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return false; - - if (wp_index >= m_max_hwp_supported) - return false; - - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; - uint32_t tempControl = m_hwp_regs[wp_index].control; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].control &= ~1; - m_hwp_regs[wp_index].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) { - m_hwp_regs[wp_index].control = tempControl; - m_hwp_regs[wp_index].address = tempAddr; - - return false; - } - - return true; -} - -Status NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints() { - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return error; - - lldb::addr_t tempAddr = 0; - uint32_t tempControl = 0; - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - if (m_hwp_regs[i].control & 0x01) { - // Create a backup we can revert to in case of failure. - tempAddr = m_hwp_regs[i].address; - tempControl = m_hwp_regs[i].control; - - // Clear watchpoints in local cache - m_hwp_regs[i].control &= ~1; - m_hwp_regs[i].address = 0; - - // Ptrace call to update hardware debug registers - error = WriteHardwareDebugRegs(eDREGTypeWATCH); - - if (error.Fail()) { - m_hwp_regs[i].control = tempControl; - m_hwp_regs[i].address = tempAddr; - - return error; - } - } - } - - return Status(); -} - -uint32_t -NativeRegisterContextLinux_arm64::GetWatchpointSize(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) { - case 0x01: - return 1; - case 0x03: - return 2; - case 0x0f: - return 4; - case 0xff: - return 8; - default: - return 0; - } -} -bool NativeRegisterContextLinux_arm64::WatchpointIsEnabled(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if ((m_hwp_regs[wp_index].control & 0x1) == 0x1) - return true; - else - return false; -} - -Status NativeRegisterContextLinux_arm64::GetWatchpointHitIndex( - uint32_t &wp_index, lldb::addr_t trap_addr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); - - uint32_t watch_size; - lldb::addr_t watch_addr; - - for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { - watch_size = GetWatchpointSize(wp_index); - watch_addr = m_hwp_regs[wp_index].address; - - if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && - trap_addr < watch_addr + watch_size) { - m_hwp_regs[wp_index].hit_addr = trap_addr; - return Status(); - } - } - - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -lldb::addr_t -NativeRegisterContextLinux_arm64::GetWatchpointAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].real_addr; - else - return LLDB_INVALID_ADDRESS; -} - -lldb::addr_t -NativeRegisterContextLinux_arm64::GetWatchpointHitAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].hit_addr; - else - return LLDB_INVALID_ADDRESS; -} - -Status NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { - if (!m_refresh_hwdebug_info) { - return Status(); - } - - ::pid_t tid = m_thread.GetID(); - - int regset = NT_ARM_HW_WATCH; - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - Status error; - - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof(dreg_state); - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, - &ioVec, ioVec.iov_len); - - if (error.Fail()) - return error; - - m_max_hwp_supported = dreg_state.dbg_info & 0xff; - - regset = NT_ARM_HW_BREAK; - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, - &ioVec, ioVec.iov_len); - - if (error.Fail()) - return error; - - m_max_hbp_supported = dreg_state.dbg_info & 0xff; - m_refresh_hwdebug_info = false; - - return error; -} - -Status NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(int hwbType) { - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - Status error; - - memset(&dreg_state, 0, sizeof(dreg_state)); - ioVec.iov_base = &dreg_state; - - if (hwbType == eDREGTypeWATCH) { - hwbType = NT_ARM_HW_WATCH; - ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + - (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported); - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address; - dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control; - } - } else { - hwbType = NT_ARM_HW_BREAK; - ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) + - (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported); - - for (uint32_t i = 0; i < m_max_hbp_supported; i++) { - dreg_state.dbg_regs[i].addr = m_hbr_regs[i].address; - dreg_state.dbg_regs[i].ctrl = m_hbr_regs[i].control; - } - } - - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), - &hwbType, &ioVec, ioVec.iov_len); -} - -Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( - uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) { - Status error; - if (offset > sizeof(struct user_pt_regs)) { - offset -= sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) { - error.SetErrorString("invalid offset value"); - return error; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); - if (error.Success()) { - value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, - m_thread.GetProcess().GetByteOrder()); - } - } else { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); - if (error.Success()) { - value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, - m_thread.GetProcess().GetByteOrder()); - } - } - return error; -} - -Status NativeRegisterContextLinux_arm64::DoWriteRegisterValue( - uint32_t offset, const char *reg_name, const RegisterValue &value) { - Status error; - ::pid_t tid = m_thread.GetID(); - if (offset > sizeof(struct user_pt_regs)) { - offset -= sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) { - error.SetErrorString("invalid offset value"); - return error; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, - &ioVec, sizeof regs); - - if (error.Success()) { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), - 16); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, - &ioVec, sizeof regs); - } - } else { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, ®set, - &ioVec, sizeof regs); - if (error.Success()) { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), - 8); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, ®set, - &ioVec, sizeof regs); - } - } - return error; -} - -Status NativeRegisterContextLinux_arm64::DoReadGPR(void *buf, size_t buf_size) { - int regset = NT_PRSTATUS; - struct iovec ioVec; - Status error; - - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), - ®set, &ioVec, buf_size); -} - -Status NativeRegisterContextLinux_arm64::DoWriteGPR(void *buf, - size_t buf_size) { - int regset = NT_PRSTATUS; - struct iovec ioVec; - Status error; - - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), - ®set, &ioVec, buf_size); -} - -Status NativeRegisterContextLinux_arm64::DoReadFPR(void *buf, size_t buf_size) { - int regset = NT_FPREGSET; - struct iovec ioVec; - Status error; - - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_thread.GetID(), - ®set, &ioVec, buf_size); -} - -Status NativeRegisterContextLinux_arm64::DoWriteFPR(void *buf, - size_t buf_size) { - int regset = NT_FPREGSET; - struct iovec ioVec; - Status error; - - ioVec.iov_base = buf; - ioVec.iov_len = buf_size; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(), - ®set, &ioVec, buf_size); -} - -uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( - const RegisterInfo *reg_info) const { - return reg_info->byte_offset - - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; -} - -#endif // defined (__arm64__) || defined (__aarch64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h deleted file mode 100644 index c859d4249d053..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ /dev/null @@ -1,169 +0,0 @@ -//===-- NativeRegisterContextLinux_arm64.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__arm64__) || defined(__aarch64__) - -#ifndef lldb_NativeRegisterContextLinux_arm64_h -#define lldb_NativeRegisterContextLinux_arm64_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - uint32_t GetUserRegisterCount() const override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - //------------------------------------------------------------------ - // Hardware breakpoints/watchpoint management functions - //------------------------------------------------------------------ - - uint32_t NumSupportedHardwareBreakpoints() override; - - uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - - bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - - Status ClearAllHardwareBreakpoints() override; - - Status GetHardwareBreakHitIndex(uint32_t &bp_index, - lldb::addr_t trap_addr) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - Status ClearAllHardwareWatchpoints() override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t GetWatchpointSize(uint32_t wp_index); - - bool WatchpointIsEnabled(uint32_t wp_index); - - // Debug register type select - enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK }; - -protected: - Status DoReadRegisterValue(uint32_t offset, const char *reg_name, - uint32_t size, RegisterValue &value) override; - - Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value) override; - - Status DoReadGPR(void *buf, size_t buf_size) override; - - Status DoWriteGPR(void *buf, size_t buf_size) override; - - Status DoReadFPR(void *buf, size_t buf_size) override; - - Status DoWriteFPR(void *buf, size_t buf_size) override; - - void *GetGPRBuffer() override { return &m_gpr_arm64; } - - void *GetFPRBuffer() override { return &m_fpr; } - - size_t GetFPRSize() override { return sizeof(m_fpr); } - -private: - struct RegInfo { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - - uint32_t first_fpr_v; - uint32_t last_fpr_v; - - uint32_t gpr_flags; - }; - - // based on RegisterContextDarwin_arm64.h - struct VReg { - uint8_t bytes[16]; - }; - - // based on RegisterContextDarwin_arm64.h - struct FPU { - VReg v[32]; - uint32_t fpsr; - uint32_t fpcr; - }; - - uint64_t m_gpr_arm64[k_num_gpr_registers_arm64]; // 64-bit general purpose - // registers. - RegInfo m_reg_info; - FPU m_fpr; // floating-point registers including extended register sets. - - // Debug register info for hardware breakpoints and watchpoints management. - struct DREG { - lldb::addr_t address; // Breakpoint/watchpoint address value. - lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception - // occurred. - lldb::addr_t real_addr; // Address value that should cause target to stop. - uint32_t control; // Breakpoint/watchpoint control value. - uint32_t refcount; // Serves as enable/disable and reference counter. - }; - - struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints - struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints - - uint32_t m_max_hwp_supported; - uint32_t m_max_hbp_supported; - bool m_refresh_hwdebug_info; - - bool IsGPR(unsigned reg) const; - - bool IsFPR(unsigned reg) const; - - Status ReadHardwareDebugInfo(); - - Status WriteHardwareDebugRegs(int hwbType); - - uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_arm64_h - -#endif // defined (__arm64__) || defined (__aarch64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp deleted file mode 100644 index d641056a04401..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ /dev/null @@ -1,1053 +0,0 @@ -//===-- NativeRegisterContextLinux_mips64.cpp ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__mips__) - -#include "NativeRegisterContextLinux_mips64.h" - - -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "lldb/Core/EmulateInstruction.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-enumerations.h" -#include "lldb/lldb-private-enumerations.h" -#define NT_MIPS_MSA 0x600 -#define CONFIG5_FRE (1 << 8) -#define SR_FR (1 << 26) -#define NUM_REGISTERS 32 - -#include <asm/ptrace.h> -#include <sys/ptrace.h> - -#ifndef PTRACE_GET_WATCH_REGS -enum pt_watch_style { pt_watch_style_mips32, pt_watch_style_mips64 }; -struct mips32_watch_regs { - uint32_t watchlo[8]; - uint16_t watchhi[8]; - uint16_t watch_masks[8]; - uint32_t num_valid; -} __attribute__((aligned(8))); - -struct mips64_watch_regs { - uint64_t watchlo[8]; - uint16_t watchhi[8]; - uint16_t watch_masks[8]; - uint32_t num_valid; -} __attribute__((aligned(8))); - -struct pt_watch_regs { - enum pt_watch_style style; - union { - struct mips32_watch_regs mips32; - struct mips64_watch_regs mips64; - }; -}; - -#define PTRACE_GET_WATCH_REGS 0xd0 -#define PTRACE_SET_WATCH_REGS 0xd1 -#endif - -#define W (1 << 0) -#define R (1 << 1) -#define I (1 << 2) - -#define IRW (I | R | W) - -#ifndef PTRACE_GETREGSET -#define PTRACE_GETREGSET 0x4204 -#endif -struct pt_watch_regs default_watch_regs; - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - return llvm::make_unique<NativeRegisterContextLinux_mips64>(target_arch, - native_thread); -} - -#define REG_CONTEXT_SIZE \ - (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR_linux_mips) + \ - sizeof(MSA_linux_mips)) - -// ---------------------------------------------------------------------------- -// NativeRegisterContextLinux_mips64 members. -// ---------------------------------------------------------------------------- - -static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) { - if ((target_arch.GetMachine() == llvm::Triple::mips) || - (target_arch.GetMachine() == llvm::Triple::mipsel)) { - // 32-bit hosts run with a RegisterContextLinux_mips context. - return new RegisterContextLinux_mips( - target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); - } else { - return new RegisterContextLinux_mips64( - target_arch, NativeRegisterContextLinux_mips64::IsMSAAvailable()); - } -} - -NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - CreateRegisterInfoInterface(target_arch)) { - switch (target_arch.GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - m_reg_info.num_registers = k_num_registers_mips; - m_reg_info.num_gpr_registers = k_num_gpr_registers_mips; - m_reg_info.num_fpr_registers = k_num_fpr_registers_mips; - m_reg_info.last_gpr = k_last_gpr_mips; - m_reg_info.first_fpr = k_first_fpr_mips; - m_reg_info.last_fpr = k_last_fpr_mips; - m_reg_info.first_msa = k_first_msa_mips; - m_reg_info.last_msa = k_last_msa_mips; - break; - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - m_reg_info.num_registers = k_num_registers_mips64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_mips64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_mips64; - m_reg_info.last_gpr = k_last_gpr_mips64; - m_reg_info.first_fpr = k_first_fpr_mips64; - m_reg_info.last_fpr = k_last_fpr_mips64; - m_reg_info.first_msa = k_first_msa_mips64; - m_reg_info.last_msa = k_last_msa_mips64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Initialize m_iovec to point to the buffer and buffer size using the - // conventions of Berkeley style UIO structures, as required by PTRACE - // extensions. - m_iovec.iov_base = &m_msa; - m_iovec.iov_len = sizeof(MSA_linux_mips); - - // init h/w watchpoint addr map - for (int index = 0; index <= MAX_NUM_WP; index++) - hw_addr_map[index] = LLDB_INVALID_ADDRESS; - - ::memset(&m_gpr, 0, sizeof(GPR_linux_mips)); - ::memset(&m_fpr, 0, sizeof(FPR_linux_mips)); - ::memset(&m_msa, 0, sizeof(MSA_linux_mips)); -} - -uint32_t NativeRegisterContextLinux_mips64::GetRegisterSetCount() const { - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: { - const auto context = static_cast<const RegisterContextLinux_mips64 &> - (GetRegisterInfoInterface()); - return context.GetRegisterSetCount(); - } - case llvm::Triple::mips: - case llvm::Triple::mipsel: { - const auto context = static_cast<const RegisterContextLinux_mips &> - (GetRegisterInfoInterface()); - return context.GetRegisterSetCount(); - } - default: - llvm_unreachable("Unhandled target architecture."); - } -} - -lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation( - lldb::addr_t fail_value) { - Status error; - RegisterValue pc_value; - lldb::addr_t pc = fail_value; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); - LLDB_LOG(log, "Reading PC from breakpoint location"); - - // PC register is at index 34 of the register array - const RegisterInfo *const pc_info_p = GetRegisterInfoAtIndex(gpr_pc_mips64); - - error = ReadRegister(pc_info_p, pc_value); - if (error.Success()) { - pc = pc_value.GetAsUInt64(); - - // CAUSE register is at index 37 of the register array - const RegisterInfo *const cause_info_p = - GetRegisterInfoAtIndex(gpr_cause_mips64); - RegisterValue cause_value; - - ReadRegister(cause_info_p, cause_value); - - uint64_t cause = cause_value.GetAsUInt64(); - LLDB_LOG(log, "PC {0:x} cause {1:x}", pc, cause); - - /* - * The breakpoint might be in a delay slot. In this case PC points - * to the delayed branch instruction rather then the instruction - * in the delay slot. If the CAUSE.BD flag is set then adjust the - * PC based on the size of the branch instruction. - */ - if ((cause & (1 << 31)) != 0) { - lldb::addr_t branch_delay = 0; - branch_delay = - 4; // FIXME - Adjust according to size of branch instruction at PC - pc = pc + branch_delay; - pc_value.SetUInt64(pc); - WriteRegister(pc_info_p, pc_value); - LLDB_LOG(log, "New PC {0:x}", pc); - } - } - - return pc; -} - -const RegisterSet * -NativeRegisterContextLinux_mips64::GetRegisterSet(uint32_t set_index) const { - if (set_index >= GetRegisterSetCount()) - return nullptr; - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: { - const auto context = static_cast<const RegisterContextLinux_mips64 &> - (GetRegisterInfoInterface()); - return context.GetRegisterSet(set_index); - } - case llvm::Triple::mips: - case llvm::Triple::mipsel: { - const auto context = static_cast<const RegisterContextLinux_mips &> - (GetRegisterInfoInterface()); - return context.GetRegisterSet(set_index); - } - default: - llvm_unreachable("Unhandled target architecture."); - } -} - -lldb_private::Status -NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - uint8_t byte_size = reg_info->byte_size; - if (reg == LLDB_INVALID_REGNUM) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " - "register, cannot read directly", - reg_info->name); - return error; - } - - if (IsMSA(reg) && !IsMSAAvailable()) { - error.SetErrorString("MSA not available on this processor"); - return error; - } - - if (IsMSA(reg) || IsFPR(reg)) { - uint8_t *src = nullptr; - lldbassert(reg_info->byte_offset < sizeof(UserArea)); - - error = ReadCP1(); - - if (!error.Success()) { - error.SetErrorString("failed to read co-processor 1 register"); - return error; - } - - if (IsFPR(reg)) { - if (IsFR0() && (byte_size != 4)) { - byte_size = 4; - uint8_t ptrace_index; - ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; - src = ReturnFPOffset(ptrace_index, reg_info->byte_offset); - } else - src = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr); - } else - src = (uint8_t *)&m_msa + reg_info->byte_offset - - (sizeof(m_gpr) + sizeof(m_fpr)); - switch (byte_size) { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - case 16: - reg_value.SetBytes((const void *)src, 16, GetByteOrder()); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, - reg_info->byte_size); - break; - } - } else { - error = ReadRegisterRaw(reg, reg_value); - } - - return error; -} - -lldb_private::Status NativeRegisterContextLinux_mips64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - Status error; - - assert(reg_info && "reg_info is null"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name - ? reg_info->name - : "<unknown register>"); - - if (IsMSA(reg_index) && !IsMSAAvailable()) { - error.SetErrorString("MSA not available on this processor"); - return error; - } - - if (IsFPR(reg_index) || IsMSA(reg_index)) { - uint8_t *dst = nullptr; - uint64_t *src = nullptr; - uint8_t byte_size = reg_info->byte_size; - lldbassert(reg_info->byte_offset < sizeof(UserArea)); - - // Initialise the FP and MSA buffers by reading all co-processor 1 - // registers - ReadCP1(); - - if (IsFPR(reg_index)) { - if (IsFR0() && (byte_size != 4)) { - byte_size = 4; - uint8_t ptrace_index; - ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; - dst = ReturnFPOffset(ptrace_index, reg_info->byte_offset); - } else - dst = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr); - } else - dst = (uint8_t *)&m_msa + reg_info->byte_offset - - (sizeof(m_gpr) + sizeof(m_fpr)); - switch (byte_size) { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - case 16: - src = (uint64_t *)reg_value.GetBytes(); - *(uint64_t *)dst = *src; - *(uint64_t *)(dst + 8) = *(src + 1); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, - reg_info->byte_size); - break; - } - error = WriteCP1(); - if (!error.Success()) { - error.SetErrorString("failed to write co-processor 1 register"); - return error; - } - } else { - error = WriteRegisterRaw(reg_index, reg_value); - } - - return error; -} - -Status NativeRegisterContextLinux_mips64::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - - error = ReadGPR(); - if (!error.Success()) { - error.SetErrorString("ReadGPR() failed"); - return error; - } - - error = ReadCP1(); - if (!error.Success()) { - error.SetErrorString("ReadCP1() failed"); - return error; - } - - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - - ::memcpy(dst, &m_gpr, GetRegisterInfoInterface().GetGPRSize()); - dst += GetRegisterInfoInterface().GetGPRSize(); - - ::memcpy(dst, &m_fpr, GetFPRSize()); - dst += GetFPRSize(); - - ::memcpy(dst, &m_msa, sizeof(MSA_linux_mips)); - - return error; -} - -Status NativeRegisterContextLinux_mips64::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_mips64::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_mips64::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_mips64::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - - ::memcpy(&m_gpr, src, GetRegisterInfoInterface().GetGPRSize()); - src += GetRegisterInfoInterface().GetGPRSize(); - - ::memcpy(&m_fpr, src, GetFPRSize()); - src += GetFPRSize(); - - ::memcpy(&m_msa, src, sizeof(MSA_linux_mips)); - - error = WriteGPR(); - if (!error.Success()) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_mips64::%s WriteGPR() failed", - __FUNCTION__); - return error; - } - - error = WriteCP1(); - if (!error.Success()) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_mips64::%s WriteCP1() failed", - __FUNCTION__); - return error; - } - - return error; -} - -Status NativeRegisterContextLinux_mips64::ReadCP1() { - Status error; - - uint8_t *src = nullptr; - uint8_t *dst = nullptr; - - lldb::ByteOrder byte_order = GetByteOrder(); - - bool IsBigEndian = (byte_order == lldb::eByteOrderBig); - - if (IsMSAAvailable()) { - error = NativeRegisterContextLinux::ReadRegisterSet( - &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); - src = (uint8_t *)&m_msa + (IsBigEndian * 8); - dst = (uint8_t *)&m_fpr; - for (int i = 0; i < NUM_REGISTERS; i++) { - // Copy fp values from msa buffer fetched via ptrace - *(uint64_t *)dst = *(uint64_t *)src; - src = src + 16; - dst = dst + 8; - } - m_fpr.fir = m_msa.fir; - m_fpr.fcsr = m_msa.fcsr; - m_fpr.config5 = m_msa.config5; - } else { - error = NativeRegisterContextLinux::ReadFPR(); - } - return error; -} - -uint8_t * -NativeRegisterContextLinux_mips64::ReturnFPOffset(uint8_t reg_index, - uint32_t byte_offset) { - - uint8_t *fp_buffer_ptr = nullptr; - lldb::ByteOrder byte_order = GetByteOrder(); - bool IsBigEndian = (byte_order == lldb::eByteOrderBig); - if (reg_index % 2) { - uint8_t offset_diff = (IsBigEndian) ? 8 : 4; - fp_buffer_ptr = - (uint8_t *)&m_fpr + byte_offset - offset_diff - sizeof(m_gpr); - } else { - fp_buffer_ptr = - (uint8_t *)&m_fpr + byte_offset + 4 * (IsBigEndian) - sizeof(m_gpr); - } - return fp_buffer_ptr; -} - -Status NativeRegisterContextLinux_mips64::WriteCP1() { - Status error; - - uint8_t *src = nullptr; - uint8_t *dst = nullptr; - - lldb::ByteOrder byte_order = GetByteOrder(); - - bool IsBigEndian = (byte_order == lldb::eByteOrderBig); - - if (IsMSAAvailable()) { - dst = (uint8_t *)&m_msa + (IsBigEndian * 8); - src = (uint8_t *)&m_fpr; - for (int i = 0; i < NUM_REGISTERS; i++) { - // Copy fp values to msa buffer for ptrace - *(uint64_t *)dst = *(uint64_t *)src; - dst = dst + 16; - src = src + 8; - } - m_msa.fir = m_fpr.fir; - m_msa.fcsr = m_fpr.fcsr; - m_msa.config5 = m_fpr.config5; - error = NativeRegisterContextLinux::WriteRegisterSet( - &m_iovec, sizeof(MSA_linux_mips), NT_MIPS_MSA); - } else { - error = NativeRegisterContextLinux::WriteFPR(); - } - - return error; -} - -bool NativeRegisterContextLinux_mips64::IsFR0() { - const RegisterInfo *const reg_info_p = GetRegisterInfoAtIndex(gpr_sr_mips64); - - RegisterValue reg_value; - ReadRegister(reg_info_p, reg_value); - - uint64_t value = reg_value.GetAsUInt64(); - - return (!(value & SR_FR)); -} - -bool NativeRegisterContextLinux_mips64::IsFRE() { - const RegisterInfo *const reg_info_p = - GetRegisterInfoAtIndex(gpr_config5_mips64); - - RegisterValue reg_value; - ReadRegister(reg_info_p, reg_value); - - uint64_t config5 = reg_value.GetAsUInt64(); - - return (config5 & CONFIG5_FRE); -} - -bool NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const { - return (m_reg_info.first_fpr <= reg_index && - reg_index <= m_reg_info.last_fpr); -} - -static uint32_t GetWatchHi(struct pt_watch_regs *regs, uint32_t index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watchhi[index]; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watchhi[index]; - LLDB_LOG(log, "Invalid watch register style"); - return 0; -} - -static void SetWatchHi(struct pt_watch_regs *regs, uint32_t index, - uint16_t value) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - regs->mips32.watchhi[index] = value; - else if (regs->style == pt_watch_style_mips64) - regs->mips64.watchhi[index] = value; - LLDB_LOG(log, "Invalid watch register style"); - return; -} - -static lldb::addr_t GetWatchLo(struct pt_watch_regs *regs, uint32_t index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watchlo[index]; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watchlo[index]; - LLDB_LOG(log, "Invalid watch register style"); - return LLDB_INVALID_ADDRESS; -} - -static void SetWatchLo(struct pt_watch_regs *regs, uint32_t index, - uint64_t value) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - regs->mips32.watchlo[index] = (uint32_t)value; - else if (regs->style == pt_watch_style_mips64) - regs->mips64.watchlo[index] = value; - else - LLDB_LOG(log, "Invalid watch register style"); -} - -static uint32_t GetIRWMask(struct pt_watch_regs *regs, uint32_t index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watch_masks[index] & IRW; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watch_masks[index] & IRW; - LLDB_LOG(log, "Invalid watch register style"); - return 0; -} - -static uint32_t GetRegMask(struct pt_watch_regs *regs, uint32_t index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - if (regs->style == pt_watch_style_mips32) - return regs->mips32.watch_masks[index] & ~IRW; - else if (regs->style == pt_watch_style_mips64) - return regs->mips64.watch_masks[index] & ~IRW; - LLDB_LOG(log, "Invalid watch register style"); - return 0; -} - -static lldb::addr_t GetRangeMask(lldb::addr_t mask) { - lldb::addr_t mask_bit = 1; - while (mask_bit < mask) { - mask = mask | mask_bit; - mask_bit <<= 1; - } - return mask; -} - -static int GetVacantWatchIndex(struct pt_watch_regs *regs, lldb::addr_t addr, - uint32_t size, uint32_t irw, - uint32_t num_valid) { - lldb::addr_t last_byte = addr + size - 1; - lldb::addr_t mask = GetRangeMask(addr ^ last_byte) | IRW; - lldb::addr_t base_addr = addr & ~mask; - - // Check if this address is already watched by previous watch points. - lldb::addr_t lo; - uint16_t hi; - uint32_t vacant_watches = 0; - for (uint32_t index = 0; index < num_valid; index++) { - lo = GetWatchLo(regs, index); - if (lo != 0 && irw == ((uint32_t)lo & irw)) { - hi = GetWatchHi(regs, index) | IRW; - lo &= ~(lldb::addr_t)hi; - if (addr >= lo && last_byte <= (lo + hi)) - return index; - } else - vacant_watches++; - } - - // Now try to find a vacant index - if (vacant_watches > 0) { - vacant_watches = 0; - for (uint32_t index = 0; index < num_valid; index++) { - lo = GetWatchLo(regs, index); - if (lo == 0 && irw == (GetIRWMask(regs, index) & irw)) { - if (mask <= (GetRegMask(regs, index) | IRW)) { - // It fits, we can use it. - SetWatchLo(regs, index, base_addr | irw); - SetWatchHi(regs, index, mask & ~IRW); - return index; - } else { - // It doesn't fit, but has the proper IRW capabilities - vacant_watches++; - } - } - } - - if (vacant_watches > 1) { - // Split this watchpoint accross several registers - struct pt_watch_regs regs_copy; - regs_copy = *regs; - lldb::addr_t break_addr; - uint32_t segment_size; - for (uint32_t index = 0; index < num_valid; index++) { - lo = GetWatchLo(®s_copy, index); - hi = GetRegMask(®s_copy, index) | IRW; - if (lo == 0 && irw == (hi & irw)) { - lo = addr & ~(lldb::addr_t)hi; - break_addr = lo + hi + 1; - if (break_addr >= addr + size) - segment_size = size; - else - segment_size = break_addr - addr; - mask = GetRangeMask(addr ^ (addr + segment_size - 1)); - SetWatchLo(®s_copy, index, (addr & ~mask) | irw); - SetWatchHi(®s_copy, index, mask & ~IRW); - if (break_addr >= addr + size) { - *regs = regs_copy; - return index; - } - size = addr + size - break_addr; - addr = break_addr; - } - } - } - } - return LLDB_INVALID_INDEX32; -} - -bool NativeRegisterContextLinux_mips64::IsMSA(uint32_t reg_index) const { - return (m_reg_info.first_msa <= reg_index && - reg_index <= m_reg_info.last_msa); -} - -bool NativeRegisterContextLinux_mips64::IsMSAAvailable() { - MSA_linux_mips msa_buf; - unsigned int regset = NT_MIPS_MSA; - - Status error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGSET, Host::GetCurrentProcessID(), - static_cast<void *>(®set), &msa_buf, sizeof(MSA_linux_mips)); - - if (error.Success() && msa_buf.mir) { - return true; - } - - return false; -} - -Status NativeRegisterContextLinux_mips64::IsWatchpointHit(uint32_t wp_index, - bool &is_hit) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - // reading the current state of watch regs - struct pt_watch_regs watch_readback; - Status error = DoReadWatchPointRegisterValue( - m_thread.GetID(), static_cast<void *>(&watch_readback)); - - if (GetWatchHi(&watch_readback, wp_index) & (IRW)) { - // clear hit flag in watchhi - SetWatchHi(&watch_readback, wp_index, - (GetWatchHi(&watch_readback, wp_index) & ~(IRW))); - DoWriteWatchPointRegisterValue(m_thread.GetID(), - static_cast<void *>(&watch_readback)); - - is_hit = true; - return error; - } - is_hit = false; - return error; -} - -Status NativeRegisterContextLinux_mips64::GetWatchpointHitIndex( - uint32_t &wp_index, lldb::addr_t trap_addr) { - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { - bool is_hit; - Status error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) { - wp_index = LLDB_INVALID_INDEX32; - } else if (is_hit) { - return error; - } - } - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -Status NativeRegisterContextLinux_mips64::IsWatchpointVacant(uint32_t wp_index, - bool &is_vacant) { - is_vacant = false; - return Status("MIPS TODO: " - "NativeRegisterContextLinux_mips64::IsWatchpointVacant not " - "implemented"); -} - -bool NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint( - uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; - - struct pt_watch_regs regs; - // First reading the current state of watch regs - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - - if (regs.style == pt_watch_style_mips32) { - regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index]; - regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index]; - regs.mips32.watch_masks[wp_index] = - default_watch_regs.mips32.watch_masks[wp_index]; - } else // pt_watch_style_mips64 - { - regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index]; - regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index]; - regs.mips64.watch_masks[wp_index] = - default_watch_regs.mips64.watch_masks[wp_index]; - } - - Status error = DoWriteWatchPointRegisterValue(m_thread.GetID(), - static_cast<void *>(®s)); - if (!error.Fail()) { - hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS; - return true; - } - return false; -} - -Status NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints() { - return DoWriteWatchPointRegisterValue( - m_thread.GetID(), static_cast<void *>(&default_watch_regs)); -} - -Status NativeRegisterContextLinux_mips64::SetHardwareWatchpointWithIndex( - lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { - Status error; - error.SetErrorString("MIPS TODO: " - "NativeRegisterContextLinux_mips64::" - "SetHardwareWatchpointWithIndex not implemented"); - return error; -} - -uint32_t NativeRegisterContextLinux_mips64::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - struct pt_watch_regs regs; - - // First reading the current state of watch regs - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - - // Try if a new watch point fits in this state - int index = GetVacantWatchIndex(®s, addr, size, watch_flags, - NumSupportedHardwareWatchpoints()); - - // New watchpoint doesn't fit - if (index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // It fits, so we go ahead with updating the state of watch regs - DoWriteWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - - // Storing exact address - hw_addr_map[index] = addr; - return index; -} - -lldb::addr_t -NativeRegisterContextLinux_mips64::GetWatchpointAddress(uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - - return hw_addr_map[wp_index]; -} - -struct EmulatorBaton { - lldb::addr_t m_watch_hit_addr; - NativeProcessLinux *m_process; - NativeRegisterContext *m_reg_context; - - EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) - : m_watch_hit_addr(LLDB_INVALID_ADDRESS), m_process(process), - m_reg_context(reg_context) {} -}; - -static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, void *dst, size_t length) { - size_t bytes_read; - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); - return bytes_read; -} - -static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, const void *dst, - size_t length) { - return length; -} - -static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) { - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - - const RegisterInfo *full_reg_info = - emulator_baton->m_reg_context->GetRegisterInfo( - lldb::eRegisterKindDWARF, reg_info->kinds[lldb::eRegisterKindDWARF]); - - Status error = - emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); - if (error.Success()) - return true; - - return false; -} - -static bool WriteRegisterCallback(EmulateInstruction *instruction, void *baton, - const EmulateInstruction::Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) { - if (reg_info->kinds[lldb::eRegisterKindDWARF] == dwarf_bad_mips64) { - EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); - emulator_baton->m_watch_hit_addr = reg_value.GetAsUInt64(); - } - - return true; -} - -/* - * MIPS Linux kernel returns a masked address (last 3bits are masked) - * when a HW watchpoint is hit. However user may not have set a watchpoint - * on this address. Emulate instruction at PC and find the base address of - * the load/store instruction. This will give the exact address used to - * read/write the variable. Send this exact address to client so that - * it can decide to stop or continue the thread. -*/ -lldb::addr_t -NativeRegisterContextLinux_mips64::GetWatchpointHitAddress(uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - - lldb_private::ArchSpec arch; - arch = GetRegisterInfoInterface().GetTargetArchitecture(); - std::unique_ptr<EmulateInstruction> emulator_ap( - EmulateInstruction::FindPlugin(arch, lldb_private::eInstructionTypeAny, - nullptr)); - - if (emulator_ap == nullptr) - return LLDB_INVALID_ADDRESS; - - EmulatorBaton baton( - static_cast<NativeProcessLinux *>(&m_thread.GetProcess()), this); - emulator_ap->SetBaton(&baton); - emulator_ap->SetReadMemCallback(&ReadMemoryCallback); - emulator_ap->SetReadRegCallback(&ReadRegisterCallback); - emulator_ap->SetWriteMemCallback(&WriteMemoryCallback); - emulator_ap->SetWriteRegCallback(&WriteRegisterCallback); - - if (!emulator_ap->ReadInstruction()) - return LLDB_INVALID_ADDRESS; - - if (emulator_ap->EvaluateInstruction(lldb::eEmulateInstructionOptionNone)) - return baton.m_watch_hit_addr; - - return LLDB_INVALID_ADDRESS; -} - -uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - struct pt_watch_regs regs; - static int num_valid = 0; - if (!num_valid) { - DoReadWatchPointRegisterValue(m_thread.GetID(), static_cast<void *>(®s)); - default_watch_regs = - regs; // Keeping default watch regs values for future use - switch (regs.style) { - case pt_watch_style_mips32: - num_valid = regs.mips32.num_valid; // Using num_valid as cache - return num_valid; - case pt_watch_style_mips64: - num_valid = regs.mips64.num_valid; - return num_valid; - } - LLDB_LOG(log, "Invalid watch register style"); - return 0; - } - return num_valid; -} - -Status -NativeRegisterContextLinux_mips64::ReadRegisterRaw(uint32_t reg_index, - RegisterValue &value) { - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - - if (!reg_info) - return Status("register %" PRIu32 " not found", reg_index); - - uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; - - if ((offset == ptrace_sr_mips) || (offset == ptrace_config5_mips)) - return Read_SR_Config(reg_info->byte_offset, reg_info->name, - reg_info->byte_size, value); - - return DoReadRegisterValue(offset, reg_info->name, reg_info->byte_size, - value); -} - -Status NativeRegisterContextLinux_mips64::WriteRegisterRaw( - uint32_t reg_index, const RegisterValue &value) { - const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index); - - if (!reg_info) - return Status("register %" PRIu32 " not found", reg_index); - - if (reg_info->invalidate_regs) - lldbassert(false && "reg_info->invalidate_regs is unhandled"); - - uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; - return DoWriteRegisterValue(offset, reg_info->name, value); -} - -Status NativeRegisterContextLinux_mips64::Read_SR_Config(uint32_t offset, - const char *reg_name, - uint32_t size, - RegisterValue &value) { - GPR_linux_mips regs; - ::memset(®s, 0, sizeof(GPR_linux_mips)); - - Status error = NativeProcessLinux::PtraceWrapper( - PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); - if (error.Success()) { - const lldb_private::ArchSpec &arch = - m_thread.GetProcess().GetArchitecture(); - void *target_address = ((uint8_t *)®s) + offset + - 4 * (arch.GetMachine() == llvm::Triple::mips); - value.SetUInt(*(uint32_t *)target_address, size); - } - return error; -} - -Status NativeRegisterContextLinux_mips64::DoReadWatchPointRegisterValue( - lldb::tid_t tid, void *watch_readback) { - return NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS, - m_thread.GetID(), watch_readback); -} - -Status NativeRegisterContextLinux_mips64::DoWriteWatchPointRegisterValue( - lldb::tid_t tid, void *watch_reg_value) { - return NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS, - m_thread.GetID(), watch_reg_value); -} - -#endif // defined (__mips__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h deleted file mode 100644 index c4e984a545bc6..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ /dev/null @@ -1,140 +0,0 @@ -//===-- NativeRegisterContextLinux_mips64.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__mips__) - -#ifndef lldb_NativeRegisterContextLinux_mips64_h -#define lldb_NativeRegisterContextLinux_mips64_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/RegisterContext_mips.h" -#include "Plugins/Process/Utility/lldb-mips-linux-register-enums.h" -#include <sys/uio.h> - -#define MAX_NUM_WP 8 - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_mips64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - lldb::addr_t GetPCfromBreakpointLocation( - lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override; - - lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - Status ReadCP1(); - - Status WriteCP1(); - - uint8_t *ReturnFPOffset(uint8_t reg_index, uint32_t byte_offset); - - Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - - bool ClearHardwareWatchpoint(uint32_t wp_index) override; - - Status ClearAllHardwareWatchpoints() override; - - Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, - uint32_t watch_flags, - uint32_t wp_index); - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - - static bool IsMSAAvailable(); - -protected: - Status Read_SR_Config(uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value); - - Status ReadRegisterRaw(uint32_t reg_index, RegisterValue &value) override; - - Status WriteRegisterRaw(uint32_t reg_index, - const RegisterValue &value) override; - - Status DoReadWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback); - - Status DoWriteWatchPointRegisterValue(lldb::tid_t tid, void *watch_readback); - - bool IsFR0(); - - bool IsFRE(); - - bool IsFPR(uint32_t reg_index) const; - - bool IsMSA(uint32_t reg_index) const; - - void *GetGPRBuffer() override { return &m_gpr; } - - void *GetFPRBuffer() override { return &m_fpr; } - - size_t GetFPRSize() override { return sizeof(FPR_linux_mips); } - -private: - // Info about register ranges. - struct RegInfo { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - uint32_t first_msa; - uint32_t last_msa; - }; - - RegInfo m_reg_info; - - GPR_linux_mips m_gpr; - - FPR_linux_mips m_fpr; - - MSA_linux_mips m_msa; - - lldb::addr_t hw_addr_map[MAX_NUM_WP]; - - struct iovec m_iovec; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_mips64_h - -#endif // defined (__mips__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp deleted file mode 100644 index da51fda1c80b3..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp +++ /dev/null @@ -1,804 +0,0 @@ -//===-- NativeRegisterContextLinux_ppc64le.cpp ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This implementation is related to the OpenPOWER ABI for Power Architecture -// 64-bit ELF V2 ABI - -#if defined(__powerpc64__) - -#include "NativeRegisterContextLinux_ppc64le.h" - -#include "lldb/Host/common/NativeProcessProtocol.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" - -// System includes - They have to be included after framework includes because -// they define some macros which collide with variable names in other modules -#include <sys/socket.h> -#include <elf.h> -#include <asm/ptrace.h> - -#define REG_CONTEXT_SIZE \ - (GetGPRSize() + GetFPRSize() + sizeof(m_vmx_ppc64le) + sizeof(m_vsx_ppc64le)) -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -static const uint32_t g_gpr_regnums_ppc64le[] = { - gpr_r0_ppc64le, gpr_r1_ppc64le, gpr_r2_ppc64le, gpr_r3_ppc64le, - gpr_r4_ppc64le, gpr_r5_ppc64le, gpr_r6_ppc64le, gpr_r7_ppc64le, - gpr_r8_ppc64le, gpr_r9_ppc64le, gpr_r10_ppc64le, gpr_r11_ppc64le, - gpr_r12_ppc64le, gpr_r13_ppc64le, gpr_r14_ppc64le, gpr_r15_ppc64le, - gpr_r16_ppc64le, gpr_r17_ppc64le, gpr_r18_ppc64le, gpr_r19_ppc64le, - gpr_r20_ppc64le, gpr_r21_ppc64le, gpr_r22_ppc64le, gpr_r23_ppc64le, - gpr_r24_ppc64le, gpr_r25_ppc64le, gpr_r26_ppc64le, gpr_r27_ppc64le, - gpr_r28_ppc64le, gpr_r29_ppc64le, gpr_r30_ppc64le, gpr_r31_ppc64le, - gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le, - gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le, - gpr_trap_ppc64le, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static const uint32_t g_fpr_regnums_ppc64le[] = { - fpr_f0_ppc64le, fpr_f1_ppc64le, fpr_f2_ppc64le, fpr_f3_ppc64le, - fpr_f4_ppc64le, fpr_f5_ppc64le, fpr_f6_ppc64le, fpr_f7_ppc64le, - fpr_f8_ppc64le, fpr_f9_ppc64le, fpr_f10_ppc64le, fpr_f11_ppc64le, - fpr_f12_ppc64le, fpr_f13_ppc64le, fpr_f14_ppc64le, fpr_f15_ppc64le, - fpr_f16_ppc64le, fpr_f17_ppc64le, fpr_f18_ppc64le, fpr_f19_ppc64le, - fpr_f20_ppc64le, fpr_f21_ppc64le, fpr_f22_ppc64le, fpr_f23_ppc64le, - fpr_f24_ppc64le, fpr_f25_ppc64le, fpr_f26_ppc64le, fpr_f27_ppc64le, - fpr_f28_ppc64le, fpr_f29_ppc64le, fpr_f30_ppc64le, fpr_f31_ppc64le, - fpr_fpscr_ppc64le, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static const uint32_t g_vmx_regnums_ppc64le[] = { - vmx_vr0_ppc64le, vmx_vr1_ppc64le, vmx_vr2_ppc64le, vmx_vr3_ppc64le, - vmx_vr4_ppc64le, vmx_vr5_ppc64le, vmx_vr6_ppc64le, vmx_vr7_ppc64le, - vmx_vr8_ppc64le, vmx_vr9_ppc64le, vmx_vr10_ppc64le, vmx_vr11_ppc64le, - vmx_vr12_ppc64le, vmx_vr13_ppc64le, vmx_vr14_ppc64le, vmx_vr15_ppc64le, - vmx_vr16_ppc64le, vmx_vr17_ppc64le, vmx_vr18_ppc64le, vmx_vr19_ppc64le, - vmx_vr20_ppc64le, vmx_vr21_ppc64le, vmx_vr22_ppc64le, vmx_vr23_ppc64le, - vmx_vr24_ppc64le, vmx_vr25_ppc64le, vmx_vr26_ppc64le, vmx_vr27_ppc64le, - vmx_vr28_ppc64le, vmx_vr29_ppc64le, vmx_vr30_ppc64le, vmx_vr31_ppc64le, - vmx_vscr_ppc64le, vmx_vrsave_ppc64le, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static const uint32_t g_vsx_regnums_ppc64le[] = { - vsx_vs0_ppc64le, vsx_vs1_ppc64le, vsx_vs2_ppc64le, vsx_vs3_ppc64le, - vsx_vs4_ppc64le, vsx_vs5_ppc64le, vsx_vs6_ppc64le, vsx_vs7_ppc64le, - vsx_vs8_ppc64le, vsx_vs9_ppc64le, vsx_vs10_ppc64le, vsx_vs11_ppc64le, - vsx_vs12_ppc64le, vsx_vs13_ppc64le, vsx_vs14_ppc64le, vsx_vs15_ppc64le, - vsx_vs16_ppc64le, vsx_vs17_ppc64le, vsx_vs18_ppc64le, vsx_vs19_ppc64le, - vsx_vs20_ppc64le, vsx_vs21_ppc64le, vsx_vs22_ppc64le, vsx_vs23_ppc64le, - vsx_vs24_ppc64le, vsx_vs25_ppc64le, vsx_vs26_ppc64le, vsx_vs27_ppc64le, - vsx_vs28_ppc64le, vsx_vs29_ppc64le, vsx_vs30_ppc64le, vsx_vs31_ppc64le, - vsx_vs32_ppc64le, vsx_vs33_ppc64le, vsx_vs34_ppc64le, vsx_vs35_ppc64le, - vsx_vs36_ppc64le, vsx_vs37_ppc64le, vsx_vs38_ppc64le, vsx_vs39_ppc64le, - vsx_vs40_ppc64le, vsx_vs41_ppc64le, vsx_vs42_ppc64le, vsx_vs43_ppc64le, - vsx_vs44_ppc64le, vsx_vs45_ppc64le, vsx_vs46_ppc64le, vsx_vs47_ppc64le, - vsx_vs48_ppc64le, vsx_vs49_ppc64le, vsx_vs50_ppc64le, vsx_vs51_ppc64le, - vsx_vs52_ppc64le, vsx_vs53_ppc64le, vsx_vs54_ppc64le, vsx_vs55_ppc64le, - vsx_vs56_ppc64le, vsx_vs57_ppc64le, vsx_vs58_ppc64le, vsx_vs59_ppc64le, - vsx_vs60_ppc64le, vsx_vs61_ppc64le, vsx_vs62_ppc64le, vsx_vs63_ppc64le, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -namespace { -// Number of register sets provided by this context. -enum { k_num_register_sets = 4 }; -} - -static const RegisterSet g_reg_sets_ppc64le[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_ppc64le, - g_gpr_regnums_ppc64le}, - {"Floating Point Registers", "fpr", k_num_fpr_registers_ppc64le, - g_fpr_regnums_ppc64le}, - {"AltiVec/VMX Registers", "vmx", k_num_vmx_registers_ppc64le, - g_vmx_regnums_ppc64le}, - {"VSX Registers", "vsx", k_num_vsx_registers_ppc64le, - g_vsx_regnums_ppc64le}, -}; - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - switch (target_arch.GetMachine()) { - case llvm::Triple::ppc64le: - return llvm::make_unique<NativeRegisterContextLinux_ppc64le>(target_arch, - native_thread); - default: - llvm_unreachable("have no register context for architecture"); - } -} - -NativeRegisterContextLinux_ppc64le::NativeRegisterContextLinux_ppc64le( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - new RegisterInfoPOSIX_ppc64le(target_arch)) { - if (target_arch.GetMachine() != llvm::Triple::ppc64le) { - llvm_unreachable("Unhandled target architecture."); - } - - ::memset(&m_gpr_ppc64le, 0, sizeof(m_gpr_ppc64le)); - ::memset(&m_fpr_ppc64le, 0, sizeof(m_fpr_ppc64le)); - ::memset(&m_vmx_ppc64le, 0, sizeof(m_vmx_ppc64le)); - ::memset(&m_vsx_ppc64le, 0, sizeof(m_vsx_ppc64le)); - ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); -} - -uint32_t NativeRegisterContextLinux_ppc64le::GetRegisterSetCount() const { - return k_num_register_sets; -} - -const RegisterSet * -NativeRegisterContextLinux_ppc64le::GetRegisterSet(uint32_t set_index) const { - if (set_index < k_num_register_sets) - return &g_reg_sets_ppc64le[set_index]; - - return nullptr; -} - -uint32_t NativeRegisterContextLinux_ppc64le::GetUserRegisterCount() const { - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - count += g_reg_sets_ppc64le[set_index].num_registers; - return count; -} - -Status NativeRegisterContextLinux_ppc64le::ReadRegister( - const RegisterInfo *reg_info, RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - - if (IsFPR(reg)) { - error = ReadFPR(); - if (error.Fail()) - return error; - - // Get pointer to m_fpr_ppc64le variable and set the data from it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < sizeof m_fpr_ppc64le); - uint8_t *src = (uint8_t *)&m_fpr_ppc64le + fpr_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, - eByteOrderLittle, error); - } else if (IsVSX(reg)) { - uint32_t vsx_offset = CalculateVsxOffset(reg_info); - assert(vsx_offset < sizeof(m_vsx_ppc64le)); - - if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { - error = ReadVSX(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - uint64_t value[2]; - uint8_t *dst, *src; - dst = (uint8_t *)&value; - src = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; - ::memcpy(dst, src, 8); - dst += 8; - src = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; - ::memcpy(dst, src, 8); - reg_value.SetFromMemoryData(reg_info, &value, reg_info->byte_size, - eByteOrderLittle, error); - } else { - error = ReadVMX(); - if (error.Fail()) - return error; - - // Get pointer to m_vmx_ppc64le variable and set the data from it. - uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; - uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, - eByteOrderLittle, error); - } - } else if (IsVMX(reg)) { - error = ReadVMX(); - if (error.Fail()) - return error; - - // Get pointer to m_vmx_ppc64le variable and set the data from it. - uint32_t vmx_offset = CalculateVmxOffset(reg_info); - assert(vmx_offset < sizeof m_vmx_ppc64le); - uint8_t *src = (uint8_t *)&m_vmx_ppc64le + vmx_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, - eByteOrderLittle, error); - } else if (IsGPR(reg)) { - error = ReadGPR(); - if (error.Fail()) - return error; - - uint8_t *src = (uint8_t *) &m_gpr_ppc64le + reg_info->byte_offset; - reg_value.SetFromMemoryData(reg_info, src, reg_info->byte_size, - eByteOrderLittle, error); - } else { - return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " - "or VMX, read strategy unknown"); - } - - return error; -} - -Status NativeRegisterContextLinux_ppc64le::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - Status error; - if (!reg_info) - return Status("reg_info NULL"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name - ? reg_info->name - : "<unknown register>"); - - if (IsGPR(reg_index)) { - error = ReadGPR(); - if (error.Fail()) - return error; - - uint8_t *dst = (uint8_t *)&m_gpr_ppc64le + reg_info->byte_offset; - ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); - - error = WriteGPR(); - if (error.Fail()) - return error; - - return Status(); - } - - if (IsFPR(reg_index)) { - error = ReadFPR(); - if (error.Fail()) - return error; - - // Get pointer to m_fpr_ppc64le variable and set the data to it. - uint32_t fpr_offset = CalculateFprOffset(reg_info); - assert(fpr_offset < GetFPRSize()); - uint8_t *dst = (uint8_t *)&m_fpr_ppc64le + fpr_offset; - ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); - - error = WriteFPR(); - if (error.Fail()) - return error; - - return Status(); - } - - if (IsVMX(reg_index)) { - error = ReadVMX(); - if (error.Fail()) - return error; - - // Get pointer to m_vmx_ppc64le variable and set the data to it. - uint32_t vmx_offset = CalculateVmxOffset(reg_info); - assert(vmx_offset < sizeof(m_vmx_ppc64le)); - uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; - ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); - - error = WriteVMX(); - if (error.Fail()) - return error; - - return Status(); - } - - if (IsVSX(reg_index)) { - uint32_t vsx_offset = CalculateVsxOffset(reg_info); - assert(vsx_offset < sizeof(m_vsx_ppc64le)); - - if (vsx_offset < sizeof(m_vsx_ppc64le) / 2) { - error = ReadVSX(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - uint64_t value[2]; - ::memcpy(value, reg_value.GetBytes(), 16); - uint8_t *dst, *src; - src = (uint8_t *)value; - dst = (uint8_t *)&m_vsx_ppc64le + vsx_offset / 2; - ::memcpy(dst, src, 8); - src += 8; - dst = (uint8_t *)&m_fpr_ppc64le + vsx_offset / 2; - ::memcpy(dst, src, 8); - - WriteVSX(); - WriteFPR(); - } else { - error = ReadVMX(); - if (error.Fail()) - return error; - - // Get pointer to m_vmx_ppc64le variable and set the data from it. - uint32_t vmx_offset = vsx_offset - sizeof(m_vsx_ppc64le) / 2; - uint8_t *dst = (uint8_t *)&m_vmx_ppc64le + vmx_offset; - ::memcpy(dst, reg_value.GetBytes(), reg_value.GetByteSize()); - WriteVMX(); - } - - return Status(); - } - - return Status("failed - register wasn't recognized to be a GPR, FPR, VSX " - "or VMX, write strategy unknown"); -} - -Status NativeRegisterContextLinux_ppc64le::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) - return Status("failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - - error = ReadGPR(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - error = ReadVMX(); - if (error.Fail()) - return error; - - error = ReadVSX(); - if (error.Fail()) - return error; - - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - - ::memcpy(dst, &m_gpr_ppc64le, GetGPRSize()); - dst += GetGPRSize(); - ::memcpy(dst, &m_fpr_ppc64le, GetFPRSize()); - dst += GetFPRSize(); - ::memcpy(dst, &m_vmx_ppc64le, sizeof(m_vmx_ppc64le)); - dst += sizeof(m_vmx_ppc64le); - ::memcpy(dst, &m_vsx_ppc64le, sizeof(m_vsx_ppc64le)); - - return error; -} - -Status NativeRegisterContextLinux_ppc64le::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_ppc64le::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_ppc64le::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_ppc64le::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - - ::memcpy(&m_gpr_ppc64le, src, GetGPRSize()); - error = WriteGPR(); - - if (error.Fail()) - return error; - - src += GetGPRSize(); - ::memcpy(&m_fpr_ppc64le, src, GetFPRSize()); - - error = WriteFPR(); - if (error.Fail()) - return error; - - src += GetFPRSize(); - ::memcpy(&m_vmx_ppc64le, src, sizeof(m_vmx_ppc64le)); - - error = WriteVMX(); - if (error.Fail()) - return error; - - src += sizeof(m_vmx_ppc64le); - ::memcpy(&m_vsx_ppc64le, src, sizeof(m_vsx_ppc64le)); - error = WriteVSX(); - - return error; -} - -bool NativeRegisterContextLinux_ppc64le::IsGPR(unsigned reg) const { - return reg <= k_last_gpr_ppc64le; // GPR's come first. -} - -bool NativeRegisterContextLinux_ppc64le::IsFPR(unsigned reg) const { - return (k_first_fpr_ppc64le <= reg && reg <= k_last_fpr_ppc64le); -} - -Status NativeRegisterContextLinux_ppc64le::DoReadGPR( - void *buf, size_t buf_size) { - int regset = NT_PRSTATUS; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), - ®set, buf, buf_size); -} - -Status NativeRegisterContextLinux_ppc64le::DoWriteGPR( - void *buf, size_t buf_size) { - int regset = NT_PRSTATUS; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), - ®set, buf, buf_size); -} - -Status NativeRegisterContextLinux_ppc64le::DoReadFPR(void *buf, - size_t buf_size) { - int regset = NT_FPREGSET; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_thread.GetID(), - ®set, buf, buf_size); -} - -Status NativeRegisterContextLinux_ppc64le::DoWriteFPR(void *buf, - size_t buf_size) { - int regset = NT_FPREGSET; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_thread.GetID(), - ®set, buf, buf_size); -} - -uint32_t NativeRegisterContextLinux_ppc64le::CalculateFprOffset( - const RegisterInfo *reg_info) const { - return reg_info->byte_offset - - GetRegisterInfoAtIndex(k_first_fpr_ppc64le)->byte_offset; -} - -uint32_t NativeRegisterContextLinux_ppc64le::CalculateVmxOffset( - const RegisterInfo *reg_info) const { - return reg_info->byte_offset - - GetRegisterInfoAtIndex(k_first_vmx_ppc64le)->byte_offset; -} - -uint32_t NativeRegisterContextLinux_ppc64le::CalculateVsxOffset( - const RegisterInfo *reg_info) const { - return reg_info->byte_offset - - GetRegisterInfoAtIndex(k_first_vsx_ppc64le)->byte_offset; -} - -Status NativeRegisterContextLinux_ppc64le::ReadVMX() { - int regset = NT_PPC_VMX; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETVRREGS, m_thread.GetID(), - ®set, &m_vmx_ppc64le, - sizeof(m_vmx_ppc64le)); -} - -Status NativeRegisterContextLinux_ppc64le::WriteVMX() { - int regset = NT_PPC_VMX; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETVRREGS, m_thread.GetID(), - ®set, &m_vmx_ppc64le, - sizeof(m_vmx_ppc64le)); -} - -Status NativeRegisterContextLinux_ppc64le::ReadVSX() { - int regset = NT_PPC_VSX; - return NativeProcessLinux::PtraceWrapper(PTRACE_GETVSRREGS, m_thread.GetID(), - ®set, &m_vsx_ppc64le, - sizeof(m_vsx_ppc64le)); -} - -Status NativeRegisterContextLinux_ppc64le::WriteVSX() { - int regset = NT_PPC_VSX; - return NativeProcessLinux::PtraceWrapper(PTRACE_SETVSRREGS, m_thread.GetID(), - ®set, &m_vsx_ppc64le, - sizeof(m_vsx_ppc64le)); -} - -bool NativeRegisterContextLinux_ppc64le::IsVMX(unsigned reg) { - return (reg >= k_first_vmx_ppc64le) && (reg <= k_last_vmx_ppc64le); -} - -bool NativeRegisterContextLinux_ppc64le::IsVSX(unsigned reg) { - return (reg >= k_first_vsx_ppc64le) && (reg <= k_last_vsx_ppc64le); -} - -uint32_t NativeRegisterContextLinux_ppc64le::NumSupportedHardwareWatchpoints() { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return 0; - - LLDB_LOG(log, "{0}", m_max_hwp_supported); - return m_max_hwp_supported; -} - -uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, - watch_flags); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - uint32_t control_value = 0, wp_index = 0; - lldb::addr_t real_addr = addr; - uint32_t rw_mode = 0; - - // Check if we are setting watchpoint other than read/write/access Update - // watchpoint flag to match ppc64le write-read bit configuration. - switch (watch_flags) { - case eWatchpointKindWrite: - rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE; - watch_flags = 2; - break; - case eWatchpointKindRead: - rw_mode = PPC_BREAKPOINT_TRIGGER_READ; - watch_flags = 1; - break; - case (eWatchpointKindRead | eWatchpointKindWrite): - rw_mode = PPC_BREAKPOINT_TRIGGER_RW; - break; - default: - return LLDB_INVALID_INDEX32; - } - - // Check if size has a valid hardware watchpoint length. - if (size != 1 && size != 2 && size != 4 && size != 8) - return LLDB_INVALID_INDEX32; - - // Check 8-byte alignment for hardware watchpoint target address. Below is a - // hack to recalculate address and size in order to make sure we can watch - // non 8-byte alligned addresses as well. - if (addr & 0x07) { - - addr_t begin = llvm::alignDown(addr, 8); - addr_t end = llvm::alignTo(addr + size, 8); - size = llvm::PowerOf2Ceil(end - begin); - - addr = addr & (~0x07); - } - - // Setup control value - control_value = watch_flags << 3; - control_value |= ((1 << size) - 1) << 5; - control_value |= (2 << 1) | 1; - - // Iterate over stored watchpoints and find a free wp_index - wp_index = LLDB_INVALID_INDEX32; - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - if ((m_hwp_regs[i].control & 1) == 0) { - wp_index = i; // Mark last free slot - } else if (m_hwp_regs[i].address == addr) { - return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. - } - } - - if (wp_index == LLDB_INVALID_INDEX32) - return LLDB_INVALID_INDEX32; - - // Update watchpoint in local cache - m_hwp_regs[wp_index].real_addr = real_addr; - m_hwp_regs[wp_index].address = addr; - m_hwp_regs[wp_index].control = control_value; - m_hwp_regs[wp_index].mode = rw_mode; - - // PTRACE call to set corresponding watchpoint register. - error = WriteHardwareDebugRegs(); - - if (error.Fail()) { - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); - - return LLDB_INVALID_INDEX32; - } - - return wp_index; -} - -bool NativeRegisterContextLinux_ppc64le::ClearHardwareWatchpoint( - uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - // Read hardware breakpoint and watchpoint information. - Status error = ReadHardwareDebugInfo(); - - if (error.Fail()) - return false; - - if (wp_index >= m_max_hwp_supported) - return false; - - // Create a backup we can revert to in case of failure. - lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; - uint32_t tempControl = m_hwp_regs[wp_index].control; - long *tempSlot = reinterpret_cast<long *>(m_hwp_regs[wp_index].slot); - - // Update watchpoint in local cache - m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(1); - m_hwp_regs[wp_index].address = 0; - m_hwp_regs[wp_index].slot = 0; - m_hwp_regs[wp_index].mode = 0; - - // Ptrace call to update hardware debug registers - error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_DELHWDEBUG, - m_thread.GetID(), 0, tempSlot); - - if (error.Fail()) { - m_hwp_regs[wp_index].control = tempControl; - m_hwp_regs[wp_index].address = tempAddr; - m_hwp_regs[wp_index].slot = reinterpret_cast<long>(tempSlot); - - return false; - } - - return true; -} - -uint32_t -NativeRegisterContextLinux_ppc64le::GetWatchpointSize(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - unsigned control = (m_hwp_regs[wp_index].control >> 5) & 0xff; - if (llvm::isPowerOf2_32(control + 1)) { - return llvm::countPopulation(control); - } - - return 0; -} - -bool NativeRegisterContextLinux_ppc64le::WatchpointIsEnabled( - uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - return !!((m_hwp_regs[wp_index].control & 0x1) == 0x1); -} - -Status NativeRegisterContextLinux_ppc64le::GetWatchpointHitIndex( - uint32_t &wp_index, lldb::addr_t trap_addr) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); - - uint32_t watch_size; - lldb::addr_t watch_addr; - - for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { - watch_size = GetWatchpointSize(wp_index); - watch_addr = m_hwp_regs[wp_index].address; - - if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && - trap_addr <= watch_addr + watch_size) { - m_hwp_regs[wp_index].hit_addr = trap_addr; - return Status(); - } - } - - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -lldb::addr_t -NativeRegisterContextLinux_ppc64le::GetWatchpointAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].real_addr; - else - return LLDB_INVALID_ADDRESS; -} - -lldb::addr_t -NativeRegisterContextLinux_ppc64le::GetWatchpointHitAddress(uint32_t wp_index) { - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); - LLDB_LOG(log, "wp_index: {0}", wp_index); - - if (wp_index >= m_max_hwp_supported) - return LLDB_INVALID_ADDRESS; - - if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].hit_addr; - - return LLDB_INVALID_ADDRESS; -} - -Status NativeRegisterContextLinux_ppc64le::ReadHardwareDebugInfo() { - if (!m_refresh_hwdebug_info) { - return Status(); - } - - ::pid_t tid = m_thread.GetID(); - - struct ppc_debug_info hwdebug_info; - Status error; - - error = NativeProcessLinux::PtraceWrapper( - PPC_PTRACE_GETHWDBGINFO, tid, 0, &hwdebug_info, sizeof(hwdebug_info)); - - if (error.Fail()) - return error; - - m_max_hwp_supported = hwdebug_info.num_data_bps; - m_max_hbp_supported = hwdebug_info.num_instruction_bps; - m_refresh_hwdebug_info = false; - - return error; -} - -Status NativeRegisterContextLinux_ppc64le::WriteHardwareDebugRegs() { - struct ppc_hw_breakpoint reg_state; - Status error; - long ret; - - for (uint32_t i = 0; i < m_max_hwp_supported; i++) { - reg_state.addr = m_hwp_regs[i].address; - reg_state.trigger_type = m_hwp_regs[i].mode; - reg_state.version = 1; - reg_state.addr_mode = PPC_BREAKPOINT_MODE_EXACT; - reg_state.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; - reg_state.addr2 = 0; - reg_state.condition_value = 0; - - error = NativeProcessLinux::PtraceWrapper(PPC_PTRACE_SETHWDEBUG, - m_thread.GetID(), 0, ®_state, - sizeof(reg_state), &ret); - - if (error.Fail()) - return error; - - m_hwp_regs[i].slot = ret; - } - - return error; -} - -#endif // defined(__powerpc64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h deleted file mode 100644 index 2c4471962ad0d..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h +++ /dev/null @@ -1,149 +0,0 @@ -//===-- NativeRegisterContextLinux_ppc64le.h --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// This implementation is related to the OpenPOWER ABI for Power Architecture -// 64-bit ELF V2 ABI - -#if defined(__powerpc64__) - -#ifndef lldb_NativeRegisterContextLinux_ppc64le_h -#define lldb_NativeRegisterContextLinux_ppc64le_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" - -#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT -#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" -#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_ppc64le : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_ppc64le(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - uint32_t GetUserRegisterCount() const override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - //------------------------------------------------------------------ - // Hardware watchpoint management functions - //------------------------------------------------------------------ - - uint32_t NumSupportedHardwareWatchpoints() override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - lldb::addr_t GetWatchpointHitAddress(uint32_t wp_index) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t GetWatchpointSize(uint32_t wp_index); - - bool WatchpointIsEnabled(uint32_t wp_index); - -protected: - Status DoReadGPR(void *buf, size_t buf_size) override; - - Status DoWriteGPR(void *buf, size_t buf_size) override; - - Status DoReadFPR(void *buf, size_t buf_size) override; - - Status DoWriteFPR(void *buf, size_t buf_size) override; - - bool IsVMX(unsigned reg); - - bool IsVSX(unsigned reg); - - Status ReadVMX(); - - Status WriteVMX(); - - Status ReadVSX(); - - Status WriteVSX(); - - void *GetGPRBuffer() override { return &m_gpr_ppc64le; } - - void *GetFPRBuffer() override { return &m_fpr_ppc64le; } - - size_t GetFPRSize() override { return sizeof(m_fpr_ppc64le); } - -private: - GPR m_gpr_ppc64le; // 64-bit general purpose registers. - FPR m_fpr_ppc64le; // floating-point registers including extended register. - VMX m_vmx_ppc64le; // VMX registers. - VSX m_vsx_ppc64le; // Last lower bytes from first VSX registers. - - bool IsGPR(unsigned reg) const; - - bool IsFPR(unsigned reg) const; - - bool IsVMX(unsigned reg) const; - - bool IsVSX(unsigned reg) const; - - uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; - - uint32_t CalculateVmxOffset(const RegisterInfo *reg_info) const; - - uint32_t CalculateVsxOffset(const RegisterInfo *reg_info) const; - - Status ReadHardwareDebugInfo(); - - Status WriteHardwareDebugRegs(); - - // Debug register info for hardware watchpoints management. - struct DREG { - lldb::addr_t address; // Breakpoint/watchpoint address value. - lldb::addr_t hit_addr; // Address at which last watchpoint trigger - // exception occurred. - lldb::addr_t real_addr; // Address value that should cause target to stop. - uint32_t control; // Breakpoint/watchpoint control value. - uint32_t refcount; // Serves as enable/disable and reference counter. - long slot; // Saves the value returned from PTRACE_SETHWDEBUG. - int mode; // Defines if watchpoint is read/write/access. - }; - - std::array<DREG, 4> m_hwp_regs; - - // 16 is just a maximum value, query hardware for actual watchpoint count - uint32_t m_max_hwp_supported = 16; - uint32_t m_max_hbp_supported = 16; - bool m_refresh_hwdebug_info = true; -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_ppc64le_h - -#endif // defined(__powerpc64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp deleted file mode 100644 index 1bc916b69bcd1..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ /dev/null @@ -1,638 +0,0 @@ -//===-- NativeRegisterContextLinux_s390x.cpp --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__s390x__) && defined(__linux__) - -#include "NativeRegisterContextLinux_s390x.h" -#include "Plugins/Process/Linux/NativeProcessLinux.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" - -#include <asm/ptrace.h> -#include <linux/uio.h> -#include <sys/ptrace.h> - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -// ---------------------------------------------------------------------------- -// Private namespace. -// ---------------------------------------------------------------------------- - -namespace { -// s390x 64-bit general purpose registers. -static const uint32_t g_gpr_regnums_s390x[] = { - lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x, - lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x, - lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x, - lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x, - lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x, - lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x, - lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x, - lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x, - lldb_pswm_s390x, lldb_pswa_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - - 1 == - k_num_gpr_registers_s390x, - "g_gpr_regnums_s390x has wrong number of register infos"); - -// s390x 64-bit floating point registers. -static const uint32_t g_fpu_regnums_s390x[] = { - lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x, - lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x, - lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x, - lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x, - lldb_fpc_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - - 1 == - k_num_fpr_registers_s390x, - "g_fpu_regnums_s390x has wrong number of register infos"); - -// s390x Linux operating-system information. -static const uint32_t g_linux_regnums_s390x[] = { - lldb_orig_r2_s390x, lldb_last_break_s390x, lldb_system_call_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_linux_regnums_s390x) / - sizeof(g_linux_regnums_s390x[0])) - - 1 == - k_num_linux_registers_s390x, - "g_linux_regnums_s390x has wrong number of register infos"); - -// Number of register sets provided by this context. -enum { k_num_register_sets = 3 }; - -// Register sets for s390x 64-bit. -static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x, - g_gpr_regnums_s390x}, - {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x, - g_fpu_regnums_s390x}, - {"Linux Operating System Data", "linux", k_num_linux_registers_s390x, - g_linux_regnums_s390x}, -}; -} - -#define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4) - -// ---------------------------------------------------------------------------- -// Required ptrace defines. -// ---------------------------------------------------------------------------- - -#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ -#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - return llvm::make_unique<NativeRegisterContextLinux_s390x>(target_arch, - native_thread); -} - -// ---------------------------------------------------------------------------- -// NativeRegisterContextLinux_s390x members. -// ---------------------------------------------------------------------------- - -static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - return new RegisterContextLinux_s390x(target_arch); -} - -NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - CreateRegisterInfoInterface(target_arch)) { - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine()) { - case llvm::Triple::systemz: - m_reg_info.num_registers = k_num_registers_s390x; - m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; - m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; - m_reg_info.last_gpr = k_last_gpr_s390x; - m_reg_info.first_fpr = k_first_fpr_s390x; - m_reg_info.last_fpr = k_last_fpr_s390x; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Clear out the watchpoint state. - m_watchpoint_addr = LLDB_INVALID_ADDRESS; -} - -uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount() const { - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - if (IsRegisterSetAvailable(set_index)) - ++sets; - } - - return sets; -} - -uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount() const { - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - const RegisterSet *set = GetRegisterSet(set_index); - if (set) - count += set->num_registers; - } - return count; -} - -const RegisterSet * -NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const { - if (!IsRegisterSetAvailable(set_index)) - return nullptr; - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::systemz: - return &g_reg_sets_s390x[set_index]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } - - return nullptr; -} - -bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable( - uint32_t set_index) const { - return set_index < k_num_register_sets; -} - -bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const { - // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR - // register area. - return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; -} - -bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const { - return (m_reg_info.first_fpr <= reg_index && - reg_index <= m_reg_info.last_fpr); -} - -Status -NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - if (!reg_info) - return Status("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Status("register \"%s\" is an internal-only lldb register, cannot " - "read directly", - reg_info->name); - - if (IsGPR(reg)) { - s390_regs regs; - Status error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Status(); - } - - if (IsFPR(reg)) { - s390_fp_regs fp_regs; - Status error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within FPR, not the whole user area. - uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Status(); - } - - if (reg == lldb_last_break_s390x) { - uint64_t last_break; - Status error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); - if (error.Fail()) - return error; - - reg_value.SetUInt64(last_break); - return Status(); - } - - if (reg == lldb_system_call_s390x) { - uint32_t system_call; - Status error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - if (error.Fail()) - return error; - - reg_value.SetUInt32(system_call); - return Status(); - } - - return Status("failed - register wasn't recognized"); -} - -Status NativeRegisterContextLinux_s390x::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - if (!reg_info) - return Status("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Status("register \"%s\" is an internal-only lldb register, cannot " - "write directly", - reg_info->name); - - if (IsGPR(reg)) { - s390_regs regs; - Status error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteGPR(®s, sizeof(regs)); - } - - if (IsFPR(reg)) { - s390_fp_regs fp_regs; - Status error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within fp_regs, not the whole user area. - uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteFPR(&fp_regs, sizeof(fp_regs)); - } - - if (reg == lldb_last_break_s390x) { - return Status("The last break address is read-only"); - } - - if (reg == lldb_system_call_s390x) { - uint32_t system_call = reg_value.GetAsUInt32(); - return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - } - - return Status("failed - register wasn't recognized"); -} - -Status NativeRegisterContextLinux_s390x::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) { - error.SetErrorStringWithFormat( - "failed to allocate DataBufferHeap instance of size %" PRIu64, - REG_CONTEXT_SIZE); - return error; - } - - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 - " returned a null pointer", - REG_CONTEXT_SIZE); - return error; - } - - error = DoReadGPR(dst, sizeof(s390_regs)); - dst += sizeof(s390_regs); - if (error.Fail()) - return error; - - error = DoReadFPR(dst, sizeof(s390_fp_regs)); - dst += sizeof(s390_fp_regs); - if (error.Fail()) - return error; - - // Ignore errors if the regset is unsupported (happens on older kernels). - DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); - dst += 4; - - // To enable inferior function calls while the process is stopped in an - // interrupted system call, we need to clear the system call flag. It will be - // restored to its original value by WriteAllRegisterValues. Again we ignore - // error if the regset is unsupported. - uint32_t system_call = 0; - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - - return error; -} - -Status NativeRegisterContextLinux_s390x::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched " - "data size, expected %" PRIu64 ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - - error = DoWriteGPR(src, sizeof(s390_regs)); - src += sizeof(s390_regs); - if (error.Fail()) - return error; - - error = DoWriteFPR(src, sizeof(s390_fp_regs)); - src += sizeof(s390_fp_regs); - if (error.Fail()) - return error; - - // Ignore errors if the regset is unsupported (happens on older kernels). - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); - src += 4; - - return error; -} - -Status NativeRegisterContextLinux_s390x::DoReadRegisterValue( - uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) { - return Status("DoReadRegisterValue unsupported"); -} - -Status NativeRegisterContextLinux_s390x::DoWriteRegisterValue( - uint32_t offset, const char *reg_name, const RegisterValue &value) { - return Status("DoWriteRegisterValue unsupported"); -} - -Status NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, - void *buf, - size_t buf_size) { - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; - - return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, - m_thread.GetID(), &parea); -} - -Status NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, - const void *buf, - size_t buf_size) { - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; - - return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, - m_thread.GetID(), &parea); -} - -Status NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) { - assert(buf_size == sizeof(s390_regs)); - return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); -} - -Status NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, - size_t buf_size) { - assert(buf_size == sizeof(s390_regs)); - return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); -} - -Status NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) { - assert(buf_size == sizeof(s390_fp_regs)); - return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); -} - -Status NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, - size_t buf_size) { - assert(buf_size == sizeof(s390_fp_regs)); - return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); -} - -Status NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, - void *buf, - size_t buf_size) { - struct iovec iov; - iov.iov_base = buf; - iov.iov_len = buf_size; - - return ReadRegisterSet(&iov, buf_size, regset); -} - -Status NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, - const void *buf, - size_t buf_size) { - struct iovec iov; - iov.iov_base = const_cast<void *>(buf); - iov.iov_len = buf_size; - - return WriteRegisterSet(&iov, buf_size, regset); -} - -Status NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, - bool &is_hit) { - per_lowcore_bits per_lowcore; - - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) { - is_hit = false; - return Status(); - } - - Status error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), - &per_lowcore, sizeof(per_lowcore)); - if (error.Fail()) { - is_hit = false; - return error; - } - - is_hit = (per_lowcore.perc_storage_alteration == 1 && - per_lowcore.perc_store_real_address == 0); - - if (is_hit) { - // Do not report this watchpoint again. - memset(&per_lowcore, 0, sizeof(per_lowcore)); - PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, - sizeof(per_lowcore)); - } - - return Status(); -} - -Status NativeRegisterContextLinux_s390x::GetWatchpointHitIndex( - uint32_t &wp_index, lldb::addr_t trap_addr) { - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { - bool is_hit; - Status error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) { - wp_index = LLDB_INVALID_INDEX32; - return error; - } else if (is_hit) { - return error; - } - } - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -Status NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, - bool &is_vacant) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; - - return Status(); -} - -bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint( - uint32_t wp_index) { - per_struct per_info; - - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; - - Status error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, - sizeof(per_info)); - if (error.Fail()) - return false; - - per_info.control_regs.bits.em_storage_alteration = 0; - per_info.control_regs.bits.storage_alt_space_ctl = 0; - per_info.starting_addr = 0; - per_info.ending_addr = 0; - - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, - sizeof(per_info)); - if (error.Fail()) - return false; - - m_watchpoint_addr = LLDB_INVALID_ADDRESS; - return true; -} - -Status NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() { - if (ClearHardwareWatchpoint(0)) - return Status(); - return Status("Clearing all hardware watchpoints failed."); -} - -uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - per_struct per_info; - - if (watch_flags != 0x1) - return LLDB_INVALID_INDEX32; - - if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) - return LLDB_INVALID_INDEX32; - - Status error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, - sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - per_info.control_regs.bits.em_storage_alteration = 1; - per_info.control_regs.bits.storage_alt_space_ctl = 1; - per_info.starting_addr = addr; - per_info.ending_addr = addr + size - 1; - - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, - sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; - - m_watchpoint_addr = addr; - return 0; -} - -lldb::addr_t -NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - return m_watchpoint_addr; -} - -uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() { - return 1; -} - -#endif // defined(__s390x__) && defined(__linux__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h deleted file mode 100644 index 57b1a0481512f..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h +++ /dev/null @@ -1,115 +0,0 @@ -//===-- NativeRegisterContextLinux_s390x.h ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__s390x__) && defined(__linux__) - -#ifndef lldb_NativeRegisterContextLinux_s390x_h -#define lldb_NativeRegisterContextLinux_s390x_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/RegisterContext_s390x.h" -#include "Plugins/Process/Utility/lldb-s390x-register-enums.h" - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - uint32_t GetUserRegisterCount() const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - - bool ClearHardwareWatchpoint(uint32_t wp_index) override; - - Status ClearAllHardwareWatchpoints() override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -protected: - Status DoReadRegisterValue(uint32_t offset, const char *reg_name, - uint32_t size, RegisterValue &value) override; - - Status DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value) override; - - Status DoReadGPR(void *buf, size_t buf_size) override; - - Status DoWriteGPR(void *buf, size_t buf_size) override; - - Status DoReadFPR(void *buf, size_t buf_size) override; - - Status DoWriteFPR(void *buf, size_t buf_size) override; - -private: - // Info about register ranges. - struct RegInfo { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - }; - - // Private member variables. - RegInfo m_reg_info; - lldb::addr_t m_watchpoint_addr; - - // Private member methods. - bool IsRegisterSetAvailable(uint32_t set_index) const; - - bool IsGPR(uint32_t reg_index) const; - - bool IsFPR(uint32_t reg_index) const; - - Status PeekUserArea(uint32_t offset, void *buf, size_t buf_size); - - Status PokeUserArea(uint32_t offset, const void *buf, size_t buf_size); - - Status DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size); - - Status DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size); -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_s390x_h - -#endif // defined(__s390x__) && defined(__linux__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp deleted file mode 100755 index 50bf29b094df0..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ /dev/null @@ -1,1213 +0,0 @@ -//===-- NativeRegisterContextLinux_x86_64.cpp ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__i386__) || defined(__x86_64__) - -#include "NativeRegisterContextLinux_x86_64.h" - -#include "lldb/Host/HostInfo.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Utility/RegisterContextLinux_i386.h" -#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" - -#include <linux/elf.h> - -using namespace lldb_private; -using namespace lldb_private::process_linux; - -// ---------------------------------------------------------------------------- -// Private namespace. -// ---------------------------------------------------------------------------- - -namespace { -// x86 32-bit general purpose registers. -const uint32_t g_gpr_regnums_i386[] = { - lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386, - lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386, - lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386, - lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386, - lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386, - lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386, - lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386, - lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) - - 1 == - k_num_gpr_registers_i386, - "g_gpr_regnums_i386 has wrong number of register infos"); - -// x86 32-bit floating point registers. -const uint32_t g_fpu_regnums_i386[] = { - lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386, - lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386, - lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386, - lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386, - lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386, - lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386, - lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386, - lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386, - lldb_xmm6_i386, lldb_xmm7_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) - - 1 == - k_num_fpr_registers_i386, - "g_fpu_regnums_i386 has wrong number of register infos"); - -// x86 32-bit AVX registers. -const uint32_t g_avx_regnums_i386[] = { - lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386, - lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) - - 1 == - k_num_avx_registers_i386, - " g_avx_regnums_i386 has wrong number of register infos"); - -// x64 32-bit MPX registers. -static const uint32_t g_mpx_regnums_i386[] = { - lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386, - lldb_bndcfgu_i386, lldb_bndstatus_i386, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) - - 1 == - k_num_mpx_registers_i386, - "g_mpx_regnums_x86_64 has wrong number of register infos"); - -// x86 64-bit general purpose registers. -static const uint32_t g_gpr_regnums_x86_64[] = { - lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64, - lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64, - lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64, - lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64, - lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64, - lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64, - lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64, - lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64, - lldb_r8d_x86_64, // Low 32 bits or r8 - lldb_r9d_x86_64, // Low 32 bits or r9 - lldb_r10d_x86_64, // Low 32 bits or r10 - lldb_r11d_x86_64, // Low 32 bits or r11 - lldb_r12d_x86_64, // Low 32 bits or r12 - lldb_r13d_x86_64, // Low 32 bits or r13 - lldb_r14d_x86_64, // Low 32 bits or r14 - lldb_r15d_x86_64, // Low 32 bits or r15 - lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64, - lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64, - lldb_r8w_x86_64, // Low 16 bits or r8 - lldb_r9w_x86_64, // Low 16 bits or r9 - lldb_r10w_x86_64, // Low 16 bits or r10 - lldb_r11w_x86_64, // Low 16 bits or r11 - lldb_r12w_x86_64, // Low 16 bits or r12 - lldb_r13w_x86_64, // Low 16 bits or r13 - lldb_r14w_x86_64, // Low 16 bits or r14 - lldb_r15w_x86_64, // Low 16 bits or r15 - lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64, - lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64, - lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64, - lldb_r8l_x86_64, // Low 8 bits or r8 - lldb_r9l_x86_64, // Low 8 bits or r9 - lldb_r10l_x86_64, // Low 8 bits or r10 - lldb_r11l_x86_64, // Low 8 bits or r11 - lldb_r12l_x86_64, // Low 8 bits or r12 - lldb_r13l_x86_64, // Low 8 bits or r13 - lldb_r14l_x86_64, // Low 8 bits or r14 - lldb_r15l_x86_64, // Low 8 bits or r15 - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) - - 1 == - k_num_gpr_registers_x86_64, - "g_gpr_regnums_x86_64 has wrong number of register infos"); - -// x86 64-bit floating point registers. -static const uint32_t g_fpu_regnums_x86_64[] = { - lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64, - lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64, - lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64, - lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64, - lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64, - lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64, - lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64, - lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64, - lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64, - lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64, - lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64, - lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64, - lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64, - lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) - - 1 == - k_num_fpr_registers_x86_64, - "g_fpu_regnums_x86_64 has wrong number of register infos"); - -// x86 64-bit AVX registers. -static const uint32_t g_avx_regnums_x86_64[] = { - lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64, - lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64, - lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64, - lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) - - 1 == - k_num_avx_registers_x86_64, - "g_avx_regnums_x86_64 has wrong number of register infos"); - -// x86 64-bit MPX registers. -static const uint32_t g_mpx_regnums_x86_64[] = { - lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64, - lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; -static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) - - 1 == - k_num_mpx_registers_x86_64, - "g_mpx_regnums_x86_64 has wrong number of register infos"); - -// Number of register sets provided by this context. -enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 }; - -// Register sets for x86 32-bit. -static const RegisterSet g_reg_sets_i386[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_i386, - g_gpr_regnums_i386}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_i386, - g_fpu_regnums_i386}, - {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386, - g_avx_regnums_i386}, - { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386, - g_mpx_regnums_i386}}; - -// Register sets for x86 64-bit. -static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64, - g_gpr_regnums_x86_64}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64, - g_fpu_regnums_x86_64}, - {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64, - g_avx_regnums_x86_64}, - { "Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64, - g_mpx_regnums_x86_64}}; -} - -#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR)) - -// ---------------------------------------------------------------------------- -// Required ptrace defines. -// ---------------------------------------------------------------------------- - -// Support ptrace extensions even when compiled without required kernel support -#ifndef NT_X86_XSTATE -#define NT_X86_XSTATE 0x202 -#endif -#ifndef NT_PRXFPREG -#define NT_PRXFPREG 0x46e62b7f -#endif - -// On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to -// use NT_PRXFPREG. -static inline unsigned int fxsr_regset(const ArchSpec &arch) { - return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG; -} - -// ---------------------------------------------------------------------------- -// Required MPX define. -// ---------------------------------------------------------------------------- - -// Support MPX extensions also if compiled with compiler without MPX support. -#ifndef bit_MPX -#define bit_MPX 0x4000 -#endif - -// ---------------------------------------------------------------------------- -// XCR0 extended register sets masks. -// ---------------------------------------------------------------------------- -#define mask_XSTATE_AVX (1ULL << 2) -#define mask_XSTATE_BNDREGS (1ULL << 3) -#define mask_XSTATE_BNDCFG (1ULL << 4) -#define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG) - -std::unique_ptr<NativeRegisterContextLinux> -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { - return std::unique_ptr<NativeRegisterContextLinux>( - new NativeRegisterContextLinux_x86_64(target_arch, native_thread)); -} - -// ---------------------------------------------------------------------------- -// NativeRegisterContextLinux_x86_64 members. -// ---------------------------------------------------------------------------- - -static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) { - if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { - // 32-bit hosts run with a RegisterContextLinux_i386 context. - return new RegisterContextLinux_i386(target_arch); - } else { - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the - // x86_64 register context. - return new RegisterContextLinux_x86_64(target_arch); - } -} - -NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextLinux(native_thread, - CreateRegisterInfoInterface(target_arch)), - m_xstate_type(XStateType::Invalid), m_fpr(), m_iovec(), m_ymm_set(), - m_mpx_set(), m_reg_info(), m_gpr_x86_64() { - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine()) { - case llvm::Triple::x86: - m_reg_info.num_registers = k_num_registers_i386; - m_reg_info.num_gpr_registers = k_num_gpr_registers_i386; - m_reg_info.num_fpr_registers = k_num_fpr_registers_i386; - m_reg_info.num_avx_registers = k_num_avx_registers_i386; - m_reg_info.num_mpx_registers = k_num_mpx_registers_i386; - m_reg_info.last_gpr = k_last_gpr_i386; - m_reg_info.first_fpr = k_first_fpr_i386; - m_reg_info.last_fpr = k_last_fpr_i386; - m_reg_info.first_st = lldb_st0_i386; - m_reg_info.last_st = lldb_st7_i386; - m_reg_info.first_mm = lldb_mm0_i386; - m_reg_info.last_mm = lldb_mm7_i386; - m_reg_info.first_xmm = lldb_xmm0_i386; - m_reg_info.last_xmm = lldb_xmm7_i386; - m_reg_info.first_ymm = lldb_ymm0_i386; - m_reg_info.last_ymm = lldb_ymm7_i386; - m_reg_info.first_mpxr = lldb_bnd0_i386; - m_reg_info.last_mpxr = lldb_bnd3_i386; - m_reg_info.first_mpxc = lldb_bndcfgu_i386; - m_reg_info.last_mpxc = lldb_bndstatus_i386; - m_reg_info.first_dr = lldb_dr0_i386; - m_reg_info.gpr_flags = lldb_eflags_i386; - break; - case llvm::Triple::x86_64: - m_reg_info.num_registers = k_num_registers_x86_64; - m_reg_info.num_gpr_registers = k_num_gpr_registers_x86_64; - m_reg_info.num_fpr_registers = k_num_fpr_registers_x86_64; - m_reg_info.num_avx_registers = k_num_avx_registers_x86_64; - m_reg_info.num_mpx_registers = k_num_mpx_registers_x86_64; - m_reg_info.last_gpr = k_last_gpr_x86_64; - m_reg_info.first_fpr = k_first_fpr_x86_64; - m_reg_info.last_fpr = k_last_fpr_x86_64; - m_reg_info.first_st = lldb_st0_x86_64; - m_reg_info.last_st = lldb_st7_x86_64; - m_reg_info.first_mm = lldb_mm0_x86_64; - m_reg_info.last_mm = lldb_mm7_x86_64; - m_reg_info.first_xmm = lldb_xmm0_x86_64; - m_reg_info.last_xmm = lldb_xmm15_x86_64; - m_reg_info.first_ymm = lldb_ymm0_x86_64; - m_reg_info.last_ymm = lldb_ymm15_x86_64; - m_reg_info.first_mpxr = lldb_bnd0_x86_64; - m_reg_info.last_mpxr = lldb_bnd3_x86_64; - m_reg_info.first_mpxc = lldb_bndcfgu_x86_64; - m_reg_info.last_mpxc = lldb_bndstatus_x86_64; - m_reg_info.first_dr = lldb_dr0_x86_64; - m_reg_info.gpr_flags = lldb_rflags_x86_64; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Initialize m_iovec to point to the buffer and buffer size using the - // conventions of Berkeley style UIO structures, as required by PTRACE - // extensions. - m_iovec.iov_base = &m_fpr; - m_iovec.iov_len = sizeof(m_fpr); - - // Clear out the FPR state. - ::memset(&m_fpr, 0, sizeof(m_fpr)); - - // Store byte offset of fctrl (i.e. first register of FPR) - const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); - m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; -} - -// CONSIDER after local and llgs debugging are merged, register set support can -// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual. -uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const { - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - if (IsRegisterSetAvailable(set_index)) - ++sets; - } - - return sets; -} - -uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const { - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { - const RegisterSet *set = GetRegisterSet(set_index); - if (set) - count += set->num_registers; - } - return count; -} - -const RegisterSet * -NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const { - if (!IsRegisterSetAvailable(set_index)) - return nullptr; - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86: - return &g_reg_sets_i386[set_index]; - case llvm::Triple::x86_64: - return &g_reg_sets_x86_64[set_index]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } - - return nullptr; -} - -Status -NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - Status error; - - if (!reg_info) { - error.SetErrorString("reg_info NULL"); - return error; - } - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) { - // This is likely an internal register for lldb use only and should not be - // directly queried. - error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb " - "register, cannot read directly", - reg_info->name); - return error; - } - - if (IsFPR(reg) || IsAVX(reg) || IsMPX(reg)) { - error = ReadFPR(); - if (error.Fail()) - return error; - } else { - uint32_t full_reg = reg; - bool is_subreg = reg_info->invalidate_regs && - (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM); - - if (is_subreg) { - // Read the full aligned 64-bit register. - full_reg = reg_info->invalidate_regs[0]; - } - - error = ReadRegisterRaw(full_reg, reg_value); - - if (error.Success()) { - // If our read was not aligned (for ah,bh,ch,dh), shift our returned - // value one byte to the right. - if (is_subreg && (reg_info->byte_offset & 0x1)) - reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8); - - // If our return byte size was greater than the return value reg size, - // then use the type specified by reg_info rather than the uint64_t - // default - if (reg_value.GetByteSize() > reg_info->byte_size) - reg_value.SetType(reg_info); - } - return error; - } - - if (reg_info->encoding == lldb::eEncodingVector) { - lldb::ByteOrder byte_order = GetByteOrder(); - - if (byte_order != lldb::eByteOrderInvalid) { - if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - reg_value.SetBytes(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); - if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { - // Concatenate ymm using the register halves in xmm.bytes and - // ymmh.bytes - if (CopyXSTATEtoYMM(reg, byte_order)) - reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - reg_info->byte_size, byte_order); - else { - error.SetErrorString("failed to copy ymm register value"); - return error; - } - } - if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - if (CopyXSTATEtoMPX(reg)) - reg_value.SetBytes(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, - reg_info->byte_size, byte_order); - else { - error.SetErrorString("failed to copy mpx register value"); - return error; - } - } - if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) { - if (CopyXSTATEtoMPX(reg)) - reg_value.SetBytes(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, - reg_info->byte_size, byte_order); - else { - error.SetErrorString("failed to copy mpx register value"); - return error; - } - } - - if (reg_value.GetType() != RegisterValue::eTypeBytes) - error.SetErrorString( - "write failed - type was expected to be RegisterValue::eTypeBytes"); - - return error; - } - - error.SetErrorString("byte order is invalid"); - return error; - } - - // Get pointer to m_fpr.fxsave variable and set the data from it. - - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)} - // and stores them in 'm_fpr' (of type FPR structure). To extract values of - // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR - // structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - - // byte_offset(fctrl wrt UserArea) - assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); - uint8_t *src = - (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) { - case 1: - reg_value.SetUInt8(*(uint8_t *)src); - break; - case 2: - reg_value.SetUInt16(*(uint16_t *)src); - break; - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - error.SetErrorStringWithFormat("unhandled byte size: %" PRIu32, - reg_info->byte_size); - break; - } - - return error; -} - -void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite( - uint32_t reg_index) { - XSAVE_HDR::XFeature &xstate_bv = m_fpr.xsave.header.xstate_bv; - if (IsFPR(reg_index)) { - // IsFPR considers both %st and %xmm registers as floating point, but these - // map to two features. Set both flags, just in case. - xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE; - } else if (IsAVX(reg_index)) { - // Lower bytes of some %ymm registers are shared with %xmm registers. - xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE; - } else if (IsMPX(reg_index)) { - // MPX registers map to two XSAVE features. - xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR; - } -} - -Status NativeRegisterContextLinux_x86_64::WriteRegister( - const RegisterInfo *reg_info, const RegisterValue ®_value) { - assert(reg_info && "reg_info is null"); - - const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg_index == LLDB_INVALID_REGNUM) - return Status("no lldb regnum for %s", reg_info && reg_info->name - ? reg_info->name - : "<unknown register>"); - - UpdateXSTATEforWrite(reg_index); - - if (IsGPR(reg_index)) - return WriteRegisterRaw(reg_index, reg_value); - - if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) { - if (reg_info->encoding == lldb::eEncodingVector) { - if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st) - ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm) - ::memcpy(m_fpr.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm) - ::memcpy(m_fpr.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - - if (reg_index >= m_reg_info.first_ymm && - reg_index <= m_reg_info.last_ymm) { - // Store ymm register content, and split into the register halves in - // xmm.bytes and ymmh.bytes - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) - return Status("CopyYMMtoXSTATE() failed"); - } - - if (reg_index >= m_reg_info.first_mpxr && - reg_index <= m_reg_info.last_mpxr) { - ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - if (!CopyMPXtoXSTATE(reg_index)) - return Status("CopyMPXtoXSTATE() failed"); - } - - if (reg_index >= m_reg_info.first_mpxc && - reg_index <= m_reg_info.last_mpxc) { - ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); - if (!CopyMPXtoXSTATE(reg_index)) - return Status("CopyMPXtoXSTATE() failed"); - } - } else { - // Get pointer to m_fpr.fxsave variable and set the data to it. - - // Byte offsets of all registers are calculated wrt 'UserArea' structure. - // However, WriteFPR() takes m_fpr (of type FPR structure) and writes - // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu - // registers should be written in m_fpr at byte offsets calculated wrt - // FPR structure. - - // Since, FPR structure is also one of the member of UserArea structure. - // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - - // byte_offset(fctrl wrt UserArea) - assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < - sizeof(m_fpr)); - uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - - m_fctrl_offset_in_userarea; - switch (reg_info->byte_size) { - case 1: - *(uint8_t *)dst = reg_value.GetAsUInt8(); - break; - case 2: - *(uint16_t *)dst = reg_value.GetAsUInt16(); - break; - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Status("unhandled register data size %" PRIu32, - reg_info->byte_size); - } - } - - Status error = WriteFPR(); - if (error.Fail()) - return error; - - if (IsAVX(reg_index)) { - if (!CopyYMMtoXSTATE(reg_index, GetByteOrder())) - return Status("CopyYMMtoXSTATE() failed"); - } - - if (IsMPX(reg_index)) { - if (!CopyMPXtoXSTATE(reg_index)) - return Status("CopyMPXtoXSTATE() failed"); - } - return Status(); - } - return Status("failed - register wasn't recognized to be a GPR or an FPR, " - "write strategy unknown"); -} - -Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - Status error; - - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - error = ReadGPR(); - if (error.Fail()) - return error; - - error = ReadFPR(); - if (error.Fail()) - return error; - - uint8_t *dst = data_sp->GetBytes(); - ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); - dst += GetRegisterInfoInterface().GetGPRSize(); - if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); - else if (m_xstate_type == XStateType::XSAVE) { - lldb::ByteOrder byte_order = GetByteOrder(); - - if (IsCPUFeatureAvailable(RegSet::avx)) { - // Assemble the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; - ++reg) { - if (!CopyXSTATEtoYMM(reg, byte_order)) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s " - "CopyXSTATEtoYMM() failed for reg num " - "%" PRIu32, - __FUNCTION__, reg); - return error; - } - } - } - - if (IsCPUFeatureAvailable(RegSet::mpx)) { - for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; - ++reg) { - if (!CopyXSTATEtoMPX(reg)) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s " - "CopyXSTATEtoMPX() failed for reg num " - "%" PRIu32, - __FUNCTION__, reg); - return error; - } - } - } - // Copy the extended register state including the assembled ymm registers. - ::memcpy(dst, &m_fpr, sizeof(m_fpr)); - } else { - assert(false && "how do we save the floating point registers?"); - error.SetErrorString("unsure how to save the floating point registers"); - } - /** The following code is specific to Linux x86 based architectures, - * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to - * -1 to solve the bug 23659, such a setting prevents the automatic - * decrement of the instruction pointer which was causing the SIGILL - * exception. - * **/ - - RegisterValue value((uint64_t)-1); - const RegisterInfo *reg_info = - GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax"); - if (reg_info == nullptr) - reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax"); - - if (reg_info != nullptr) - return DoWriteRegisterValue(reg_info->byte_offset, reg_info->name, value); - - return error; -} - -Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - Status error; - - if (!data_sp) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided", - __FUNCTION__); - return error; - } - - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { - error.SetErrorStringWithFormatv( - "data_sp contained mismatched data size, expected {0}, actual {1}", - REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } - - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_x86_64::%s " - "DataBuffer::GetBytes() returned a null " - "pointer", - __FUNCTION__); - return error; - } - ::memcpy(&m_gpr_x86_64, src, GetRegisterInfoInterface().GetGPRSize()); - - error = WriteGPR(); - if (error.Fail()) - return error; - - src += GetRegisterInfoInterface().GetGPRSize(); - if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); - else if (m_xstate_type == XStateType::XSAVE) - ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); - - error = WriteFPR(); - if (error.Fail()) - return error; - - if (m_xstate_type == XStateType::XSAVE) { - lldb::ByteOrder byte_order = GetByteOrder(); - - if (IsCPUFeatureAvailable(RegSet::avx)) { - // Parse the YMM register content from the register halves. - for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm; - ++reg) { - if (!CopyYMMtoXSTATE(reg, byte_order)) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s " - "CopyYMMtoXSTATE() failed for reg num " - "%" PRIu32, - __FUNCTION__, reg); - return error; - } - } - } - - if (IsCPUFeatureAvailable(RegSet::mpx)) { - for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc; - ++reg) { - if (!CopyMPXtoXSTATE(reg)) { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_x86_64::%s " - "CopyMPXtoXSTATE() failed for reg num " - "%" PRIu32, - __FUNCTION__, reg); - return error; - } - } - } - } - - return error; -} - -bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable( - RegSet feature_code) const { - if (m_xstate_type == XStateType::Invalid) { - if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail()) - return false; - } - switch (feature_code) { - case RegSet::gpr: - case RegSet::fpu: - return true; - case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by - // reading in the XCR0 area of XSAVE. - if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) - return true; - break; - case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by - // reading in the XCR0 area of XSAVE. - if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) - return true; - break; - } - return false; -} - -bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable( - uint32_t set_index) const { - uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets; - - switch (static_cast<RegSet>(set_index)) { - case RegSet::gpr: - case RegSet::fpu: - return (set_index < num_sets); - case RegSet::avx: - return IsCPUFeatureAvailable(RegSet::avx); - case RegSet::mpx: - return IsCPUFeatureAvailable(RegSet::mpx); - } - return false; -} - -bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const { - // GPRs come first. - return reg_index <= m_reg_info.last_gpr; -} - -bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const { - return (m_reg_info.first_fpr <= reg_index && - reg_index <= m_reg_info.last_fpr); -} - -Status NativeRegisterContextLinux_x86_64::WriteFPR() { - switch (m_xstate_type) { - case XStateType::FXSAVE: - return WriteRegisterSet( - &m_iovec, sizeof(m_fpr.fxsave), - fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); - case XStateType::XSAVE: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); - default: - return Status("Unrecognized FPR type."); - } -} - -bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const { - if (!IsCPUFeatureAvailable(RegSet::avx)) - return false; - return (m_reg_info.first_ymm <= reg_index && - reg_index <= m_reg_info.last_ymm); -} - -bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( - uint32_t reg_index, lldb::ByteOrder byte_order) { - if (!IsAVX(reg_index)) - return false; - - if (byte_order == lldb::eByteOrderLittle) { - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + - sizeof(XMMReg), - m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - - if (byte_order == lldb::eByteOrderBig) { - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + - sizeof(XMMReg), - m_fpr.fxsave.xmm[reg_index - m_reg_info.first_ymm].bytes, - sizeof(XMMReg)); - ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, - sizeof(YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order -} - -bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( - uint32_t reg, lldb::ByteOrder byte_order) { - if (!IsAVX(reg)) - return false; - - if (byte_order == lldb::eByteOrderLittle) { - ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); - ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(YMMHReg)); - return true; - } - - if (byte_order == lldb::eByteOrderBig) { - ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - sizeof(XMMReg)); - ::memcpy(m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, - m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); - return true; - } - return false; // unsupported or invalid byte order -} - -void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { - switch (m_xstate_type) { - case XStateType::FXSAVE: - return &m_fpr.fxsave; - case XStateType::XSAVE: - return &m_iovec; - default: - return nullptr; - } -} - -size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { - switch (m_xstate_type) { - case XStateType::FXSAVE: - return sizeof(m_fpr.fxsave); - case XStateType::XSAVE: - return sizeof(m_iovec); - default: - return 0; - } -} - -Status NativeRegisterContextLinux_x86_64::ReadFPR() { - Status error; - - // Probe XSAVE and if it is not supported fall back to FXSAVE. - if (m_xstate_type != XStateType::FXSAVE) { - error = ReadRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); - if (!error.Fail()) { - m_xstate_type = XStateType::XSAVE; - return error; - } - } - error = ReadRegisterSet( - &m_iovec, sizeof(m_fpr.xsave), - fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); - if (!error.Fail()) { - m_xstate_type = XStateType::FXSAVE; - return error; - } - return Status("Unrecognized FPR type."); -} - -bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const { - if (!IsCPUFeatureAvailable(RegSet::mpx)) - return false; - return (m_reg_info.first_mpxr <= reg_index && - reg_index <= m_reg_info.last_mpxc); -} - -bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) { - if (!IsMPX(reg)) - return false; - - if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, - m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, - sizeof(MPXReg)); - } else { - ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, - m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, - sizeof(MPXCsr)); - } - return true; -} - -bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) { - if (!IsMPX(reg)) - return false; - - if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - ::memcpy(m_fpr.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, - m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg)); - } else { - ::memcpy(m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, - m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); - } - return true; -} - -Status NativeRegisterContextLinux_x86_64::IsWatchpointHit(uint32_t wp_index, - bool &is_hit) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - RegisterValue reg_value; - Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) { - is_hit = false; - return error; - } - - uint64_t status_bits = reg_value.GetAsUInt64(); - - is_hit = status_bits & (1 << wp_index); - - return error; -} - -Status NativeRegisterContextLinux_x86_64::GetWatchpointHitIndex( - uint32_t &wp_index, lldb::addr_t trap_addr) { - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { - bool is_hit; - Status error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) { - wp_index = LLDB_INVALID_INDEX32; - return error; - } else if (is_hit) { - return error; - } - } - wp_index = LLDB_INVALID_INDEX32; - return Status(); -} - -Status NativeRegisterContextLinux_x86_64::IsWatchpointVacant(uint32_t wp_index, - bool &is_vacant) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - RegisterValue reg_value; - Status error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) { - is_vacant = false; - return error; - } - - uint64_t control_bits = reg_value.GetAsUInt64(); - - is_vacant = !(control_bits & (1 << (2 * wp_index))); - - return error; -} - -Status NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex( - lldb::addr_t addr, size_t size, uint32_t watch_flags, uint32_t wp_index) { - - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Status("Watchpoint index out of range"); - - // Read only watchpoints aren't supported on x86_64. Fall back to read/write - // waitchpoints instead. - // TODO: Add logic to detect when a write happens and ignore that watchpoint - // hit. - if (watch_flags == 0x2) - watch_flags = 0x3; - - if (watch_flags != 0x1 && watch_flags != 0x3) - return Status("Invalid read/write bits for watchpoint"); - - if (size != 1 && size != 2 && size != 4 && size != 8) - return Status("Invalid size for watchpoint"); - - bool is_vacant; - Status error = IsWatchpointVacant(wp_index, is_vacant); - if (error.Fail()) - return error; - if (!is_vacant) - return Status("Watchpoint index not vacant"); - - RegisterValue reg_value; - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) - return error; - - // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7 - uint64_t enable_bit = 1 << (2 * wp_index); - - // set bits 16-17, 20-21, 24-25, or 28-29 - // with 0b01 for write, and 0b11 for read/write - uint64_t rw_bits = watch_flags << (16 + 4 * wp_index); - - // set bits 18-19, 22-23, 26-27, or 30-31 - // with 0b00, 0b01, 0b10, or 0b11 - // for 1, 2, 8 (if supported), or 4 bytes, respectively - uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index); - - uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); - - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - - control_bits |= enable_bit | rw_bits | size_bits; - - error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr)); - if (error.Fail()) - return error; - - error = - WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); - if (error.Fail()) - return error; - - error.Clear(); - return error; -} - -bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint( - uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; - - RegisterValue reg_value; - - // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of - // the debug status register (DR6) - Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) - return false; - uint64_t bit_mask = 1 << wp_index; - uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); - if (error.Fail()) - return false; - - // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19}, - // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register - // (DR7) - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) - return false; - bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index)); - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)) - .Success(); -} - -Status NativeRegisterContextLinux_x86_64::ClearAllHardwareWatchpoints() { - RegisterValue reg_value; - - // clear bits {0-4} of the debug status register (DR6) - Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value); - if (error.Fail()) - return error; - uint64_t bit_mask = 0xF; - uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask; - error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits)); - if (error.Fail()) - return error; - - // clear bits {0-7,16-31} of the debug control register (DR7) - error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value); - if (error.Fail()) - return error; - bit_mask = 0xFF | (0xFFFF << 16); - uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask; - return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)); -} - -uint32_t NativeRegisterContextLinux_x86_64::SetHardwareWatchpoint( - lldb::addr_t addr, size_t size, uint32_t watch_flags) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); - const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); - for (uint32_t wp_index = 0; wp_index < num_hw_watchpoints; ++wp_index) { - bool is_vacant; - Status error = IsWatchpointVacant(wp_index, is_vacant); - if (is_vacant) { - error = SetHardwareWatchpointWithIndex(addr, size, watch_flags, wp_index); - if (error.Success()) - return wp_index; - } - if (error.Fail() && log) { - log->Printf("NativeRegisterContextLinux_x86_64::%s Error: %s", - __FUNCTION__, error.AsCString()); - } - } - return LLDB_INVALID_INDEX32; -} - -lldb::addr_t -NativeRegisterContextLinux_x86_64::GetWatchpointAddress(uint32_t wp_index) { - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - RegisterValue reg_value; - if (ReadRegisterRaw(m_reg_info.first_dr + wp_index, reg_value).Fail()) - return LLDB_INVALID_ADDRESS; - return reg_value.GetAsUInt64(); -} - -uint32_t NativeRegisterContextLinux_x86_64::NumSupportedHardwareWatchpoints() { - // Available debug address registers: dr0, dr1, dr2, dr3 - return 4; -} - -#endif // defined(__i386__) || defined(__x86_64__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h deleted file mode 100644 index 9dcf82f50a458..0000000000000 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ /dev/null @@ -1,149 +0,0 @@ -//===-- NativeRegisterContextLinux_x86_64.h ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#if defined(__i386__) || defined(__x86_64__) - -#ifndef lldb_NativeRegisterContextLinux_x86_64_h -#define lldb_NativeRegisterContextLinux_x86_64_h - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Utility/RegisterContext_x86.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" -#include <sys/uio.h> - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { -public: - NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); - - uint32_t GetRegisterSetCount() const override; - - const RegisterSet *GetRegisterSet(uint32_t set_index) const override; - - uint32_t GetUserRegisterCount() const override; - - Status ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - Status WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - - Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; - - Status GetWatchpointHitIndex(uint32_t &wp_index, - lldb::addr_t trap_addr) override; - - Status IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; - - bool ClearHardwareWatchpoint(uint32_t wp_index) override; - - Status ClearAllHardwareWatchpoints() override; - - Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, - uint32_t watch_flags, - uint32_t wp_index); - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags) override; - - lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - -protected: - void *GetGPRBuffer() override { return &m_gpr_x86_64; } - - void *GetFPRBuffer() override; - - size_t GetFPRSize() override; - - Status ReadFPR() override; - - Status WriteFPR() override; - -private: - // Private member types. - enum class XStateType { Invalid, FXSAVE, XSAVE }; - enum class RegSet { gpr, fpu, avx, mpx }; - - // Info about register ranges. - struct RegInfo { - uint32_t num_registers; - uint32_t num_gpr_registers; - uint32_t num_fpr_registers; - uint32_t num_avx_registers; - uint32_t num_mpx_registers; - uint32_t last_gpr; - uint32_t first_fpr; - uint32_t last_fpr; - uint32_t first_st; - uint32_t last_st; - uint32_t first_mm; - uint32_t last_mm; - uint32_t first_xmm; - uint32_t last_xmm; - uint32_t first_ymm; - uint32_t last_ymm; - uint32_t first_mpxr; - uint32_t last_mpxr; - uint32_t first_mpxc; - uint32_t last_mpxc; - uint32_t first_dr; - uint32_t gpr_flags; - }; - - // Private member variables. - mutable XStateType m_xstate_type; - FPR m_fpr; // Extended States Area, named FPR for historical reasons. - struct iovec m_iovec; - YMM m_ymm_set; - MPX m_mpx_set; - RegInfo m_reg_info; - uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64]; - uint32_t m_fctrl_offset_in_userarea; - - // Private member methods. - bool IsCPUFeatureAvailable(RegSet feature_code) const; - - bool IsRegisterSetAvailable(uint32_t set_index) const; - - bool IsGPR(uint32_t reg_index) const; - - bool IsFPR(uint32_t reg_index) const; - - bool CopyXSTATEtoYMM(uint32_t reg_index, lldb::ByteOrder byte_order); - - bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order); - - bool IsAVX(uint32_t reg_index) const; - - bool CopyXSTATEtoMPX(uint32_t reg); - - bool CopyMPXtoXSTATE(uint32_t reg); - - bool IsMPX(uint32_t reg_index) const; - - void UpdateXSTATEforWrite(uint32_t reg_index); -}; - -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h - -#endif // defined(__i386__) || defined(__x86_64__) diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp deleted file mode 100644 index b64689c9d17b0..0000000000000 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ /dev/null @@ -1,451 +0,0 @@ -//===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "NativeThreadLinux.h" - -#include <signal.h> -#include <sstream> - -#include "NativeProcessLinux.h" -#include "NativeRegisterContextLinux.h" -#include "SingleStepCheck.h" - -#include "lldb/Host/HostNativeThread.h" -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Host/linux/Support.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" -#include "lldb/lldb-enumerations.h" - -#include "llvm/ADT/SmallString.h" - -#include "Plugins/Process/POSIX/CrashReason.h" - -#include <sys/syscall.h> -// Try to define a macro to encapsulate the tgkill syscall -#define tgkill(pid, tid, sig) \ - syscall(__NR_tgkill, static_cast<::pid_t>(pid), static_cast<::pid_t>(tid), \ - sig) - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -namespace { -void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info, - const char *const header) { - switch (stop_info.reason) { - case eStopReasonNone: - log.Printf("%s: %s no stop reason", __FUNCTION__, header); - return; - case eStopReasonTrace: - log.Printf("%s: %s trace, stopping signal 0x%" PRIx32, __FUNCTION__, header, - stop_info.details.signal.signo); - return; - case eStopReasonBreakpoint: - log.Printf("%s: %s breakpoint, stopping signal 0x%" PRIx32, __FUNCTION__, - header, stop_info.details.signal.signo); - return; - case eStopReasonWatchpoint: - log.Printf("%s: %s watchpoint, stopping signal 0x%" PRIx32, __FUNCTION__, - header, stop_info.details.signal.signo); - return; - case eStopReasonSignal: - log.Printf("%s: %s signal 0x%02" PRIx32, __FUNCTION__, header, - stop_info.details.signal.signo); - return; - case eStopReasonException: - log.Printf("%s: %s exception type 0x%02" PRIx64, __FUNCTION__, header, - stop_info.details.exception.type); - return; - case eStopReasonExec: - log.Printf("%s: %s exec, stopping signal 0x%" PRIx32, __FUNCTION__, header, - stop_info.details.signal.signo); - return; - case eStopReasonPlanComplete: - log.Printf("%s: %s plan complete", __FUNCTION__, header); - return; - case eStopReasonThreadExiting: - log.Printf("%s: %s thread exiting", __FUNCTION__, header); - return; - case eStopReasonInstrumentation: - log.Printf("%s: %s instrumentation", __FUNCTION__, header); - return; - default: - log.Printf("%s: %s invalid stop reason %" PRIu32, __FUNCTION__, header, - static_cast<uint32_t>(stop_info.reason)); - } -} -} - -NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process, - lldb::tid_t tid) - : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), - m_stop_info(), - m_reg_context_up( - NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - process.GetArchitecture(), *this)), - m_stop_description() {} - -std::string NativeThreadLinux::GetName() { - NativeProcessLinux &process = GetProcess(); - - auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm"); - if (!BufferOrError) - return ""; - return BufferOrError.get()->getBuffer().rtrim('\n'); -} - -lldb::StateType NativeThreadLinux::GetState() { return m_state; } - -bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info, - std::string &description) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - description.clear(); - - switch (m_state) { - case eStateStopped: - case eStateCrashed: - case eStateExited: - case eStateSuspended: - case eStateUnloaded: - if (log) - LogThreadStopInfo(*log, m_stop_info, "m_stop_info in thread:"); - stop_info = m_stop_info; - description = m_stop_description; - if (log) - LogThreadStopInfo(*log, stop_info, "returned stop_info:"); - - return true; - - case eStateInvalid: - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - if (log) { - log->Printf("NativeThreadLinux::%s tid %" PRIu64 - " in state %s cannot answer stop reason", - __FUNCTION__, GetID(), StateAsCString(m_state)); - } - return false; - } - llvm_unreachable("unhandled StateType!"); -} - -Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, - uint32_t watch_flags, bool hardware) { - if (!hardware) - return Status("not implemented"); - if (m_state == eStateLaunching) - return Status(); - Status error = RemoveWatchpoint(addr); - if (error.Fail()) - return error; - uint32_t wp_index = - m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags); - if (wp_index == LLDB_INVALID_INDEX32) - return Status("Setting hardware watchpoint failed."); - m_watchpoint_index_map.insert({addr, wp_index}); - return Status(); -} - -Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) { - auto wp = m_watchpoint_index_map.find(addr); - if (wp == m_watchpoint_index_map.end()) - return Status(); - uint32_t wp_index = wp->second; - m_watchpoint_index_map.erase(wp); - if (m_reg_context_up->ClearHardwareWatchpoint(wp_index)) - return Status(); - return Status("Clearing hardware watchpoint failed."); -} - -Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - if (m_state == eStateLaunching) - return Status(); - - Status error = RemoveHardwareBreakpoint(addr); - if (error.Fail()) - return error; - - uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size); - - if (bp_index == LLDB_INVALID_INDEX32) - return Status("Setting hardware breakpoint failed."); - - m_hw_break_index_map.insert({addr, bp_index}); - return Status(); -} - -Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) { - auto bp = m_hw_break_index_map.find(addr); - if (bp == m_hw_break_index_map.end()) - return Status(); - - uint32_t bp_index = bp->second; - if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) { - m_hw_break_index_map.erase(bp); - return Status(); - } - - return Status("Clearing hardware breakpoint failed."); -} - -Status NativeThreadLinux::Resume(uint32_t signo) { - const StateType new_state = StateType::eStateRunning; - MaybeLogStateChange(new_state); - m_state = new_state; - - m_stop_info.reason = StopReason::eStopReasonNone; - m_stop_description.clear(); - - // If watchpoints have been set, but none on this thread, then this is a new - // thread. So set all existing watchpoints. - if (m_watchpoint_index_map.empty()) { - NativeProcessLinux &process = GetProcess(); - - const auto &watchpoint_map = process.GetWatchpointMap(); - m_reg_context_up->ClearAllHardwareWatchpoints(); - for (const auto &pair : watchpoint_map) { - const auto &wp = pair.second; - SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); - } - } - - // Set all active hardware breakpoint on all threads. - if (m_hw_break_index_map.empty()) { - NativeProcessLinux &process = GetProcess(); - - const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap(); - m_reg_context_up->ClearAllHardwareBreakpoints(); - for (const auto &pair : hw_breakpoint_map) { - const auto &bp = pair.second; - SetHardwareBreakpoint(bp.m_addr, bp.m_size); - } - } - - intptr_t data = 0; - - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; - - return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, - reinterpret_cast<void *>(data)); -} - -Status NativeThreadLinux::SingleStep(uint32_t signo) { - const StateType new_state = StateType::eStateStepping; - MaybeLogStateChange(new_state); - m_state = new_state; - m_stop_info.reason = StopReason::eStopReasonNone; - - if(!m_step_workaround) { - // If we already hava a workaround inplace, don't reset it. Otherwise, the - // destructor of the existing instance will run after the new instance has - // fetched the cpu mask, and the thread will end up with the wrong mask. - m_step_workaround = SingleStepWorkaround::Get(m_tid); - } - - intptr_t data = 0; - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; - - // If hardware single-stepping is not supported, we just do a continue. The - // breakpoint on the next instruction has been setup in - // NativeProcessLinux::Resume. - return NativeProcessLinux::PtraceWrapper( - GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP - : PTRACE_CONT, - m_tid, nullptr, reinterpret_cast<void *>(data)); -} - -void NativeThreadLinux::SetStoppedBySignal(uint32_t signo, - const siginfo_t *info) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("NativeThreadLinux::%s called with signal 0x%02" PRIx32, - __FUNCTION__, signo); - - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonSignal; - m_stop_info.details.signal.signo = signo; - - m_stop_description.clear(); - if (info) { - switch (signo) { - case SIGSEGV: - case SIGBUS: - case SIGFPE: - case SIGILL: - // In case of MIPS64 target, SI_KERNEL is generated for invalid 64bit - // address. - const auto reason = - (info->si_signo == SIGBUS && info->si_code == SI_KERNEL) - ? CrashReason::eInvalidAddress - : GetCrashReason(*info); - m_stop_description = GetCrashReasonString(reason, *info); - break; - } - } -} - -bool NativeThreadLinux::IsStopped(int *signo) { - if (!StateIsStoppedState(m_state, false)) - return false; - - // If we are stopped by a signal, return the signo. - if (signo && m_state == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonSignal) { - *signo = m_stop_info.details.signal.signo; - } - - // Regardless, we are stopped. - return true; -} - -void NativeThreadLinux::SetStopped() { - if (m_state == StateType::eStateStepping) - m_step_workaround.reset(); - - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange(new_state); - m_state = new_state; - m_stop_description.clear(); -} - -void NativeThreadLinux::SetStoppedByExec() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - if (log) - log->Printf("NativeThreadLinux::%s()", __FUNCTION__); - - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonExec; - m_stop_info.details.signal.signo = SIGSTOP; -} - -void NativeThreadLinux::SetStoppedByBreakpoint() { - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonBreakpoint; - m_stop_info.details.signal.signo = SIGTRAP; - m_stop_description.clear(); -} - -void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { - SetStopped(); - - lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); - - std::ostringstream ostr; - ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " "; - ostr << wp_index; - - /* - * MIPS: Last 3bits of the watchpoint address are masked by the kernel. For - * example: - * 'n' is at 0x120010d00 and 'm' is 0x120010d04. When a watchpoint is set at - * 'm', then - * watch exception is generated even when 'n' is read/written. To handle this - * case, - * find the base address of the load/store instruction and append it in the - * stop-info - * packet. - */ - ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index); - - m_stop_description = ostr.str(); - - m_stop_info.reason = StopReason::eStopReasonWatchpoint; - m_stop_info.details.signal.signo = SIGTRAP; -} - -bool NativeThreadLinux::IsStoppedAtBreakpoint() { - return GetState() == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonBreakpoint; -} - -bool NativeThreadLinux::IsStoppedAtWatchpoint() { - return GetState() == StateType::eStateStopped && - m_stop_info.reason == StopReason::eStopReasonWatchpoint; -} - -void NativeThreadLinux::SetStoppedByTrace() { - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonTrace; - m_stop_info.details.signal.signo = SIGTRAP; -} - -void NativeThreadLinux::SetStoppedWithNoReason() { - SetStopped(); - - m_stop_info.reason = StopReason::eStopReasonNone; - m_stop_info.details.signal.signo = 0; -} - -void NativeThreadLinux::SetExited() { - const StateType new_state = StateType::eStateExited; - MaybeLogStateChange(new_state); - m_state = new_state; - - m_stop_info.reason = StopReason::eStopReasonThreadExiting; -} - -Status NativeThreadLinux::RequestStop() { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - NativeProcessLinux &process = GetProcess(); - - lldb::pid_t pid = process.GetID(); - lldb::tid_t tid = GetID(); - - if (log) - log->Printf("NativeThreadLinux::%s requesting thread stop(pid: %" PRIu64 - ", tid: %" PRIu64 ")", - __FUNCTION__, pid, tid); - - Status err; - errno = 0; - if (::tgkill(pid, tid, SIGSTOP) != 0) { - err.SetErrorToErrno(); - if (log) - log->Printf("NativeThreadLinux::%s tgkill(%" PRIu64 ", %" PRIu64 - ", SIGSTOP) failed: %s", - __FUNCTION__, pid, tid, err.AsCString()); - } - - return err; -} - -void NativeThreadLinux::MaybeLogStateChange(lldb::StateType new_state) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - // If we're not logging, we're done. - if (!log) - return; - - // If this is a state change to the same state, we're done. - lldb::StateType old_state = m_state; - if (new_state == old_state) - return; - - LLDB_LOG(log, "pid={0}, tid={1}: changing from state {2} to {3}", - m_process.GetID(), GetID(), old_state, new_state); -} - -NativeProcessLinux &NativeThreadLinux::GetProcess() { - return static_cast<NativeProcessLinux &>(m_process); -} diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h deleted file mode 100644 index a7c4e982012d2..0000000000000 --- a/source/Plugins/Process/Linux/NativeThreadLinux.h +++ /dev/null @@ -1,119 +0,0 @@ -//===-- NativeThreadLinux.h ----------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_NativeThreadLinux_H_ -#define liblldb_NativeThreadLinux_H_ - -#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" -#include "Plugins/Process/Linux/SingleStepCheck.h" -#include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/lldb-private-forward.h" - -#include <csignal> -#include <map> -#include <memory> -#include <string> - -namespace lldb_private { -namespace process_linux { - -class NativeProcessLinux; - -class NativeThreadLinux : public NativeThreadProtocol { - friend class NativeProcessLinux; - -public: - NativeThreadLinux(NativeProcessLinux &process, lldb::tid_t tid); - - // --------------------------------------------------------------------- - // NativeThreadProtocol Interface - // --------------------------------------------------------------------- - std::string GetName() override; - - lldb::StateType GetState() override; - - bool GetStopReason(ThreadStopInfo &stop_info, - std::string &description) override; - - NativeRegisterContextLinux &GetRegisterContext() override { - return *m_reg_context_up; - } - - Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, - bool hardware) override; - - Status RemoveWatchpoint(lldb::addr_t addr) override; - - Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - - Status RemoveHardwareBreakpoint(lldb::addr_t addr) override; - -private: - // --------------------------------------------------------------------- - // Interface for friend classes - // --------------------------------------------------------------------- - - /// Resumes the thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Status Resume(uint32_t signo); - - /// Single steps the thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Status SingleStep(uint32_t signo); - - void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); - - /// Return true if the thread is stopped. - /// If stopped by a signal, indicate the signo in the signo argument. - /// Otherwise, return LLDB_INVALID_SIGNAL_NUMBER. - bool IsStopped(int *signo); - - void SetStoppedByExec(); - - void SetStoppedByBreakpoint(); - - void SetStoppedByWatchpoint(uint32_t wp_index); - - bool IsStoppedAtBreakpoint(); - - bool IsStoppedAtWatchpoint(); - - void SetStoppedByTrace(); - - void SetStoppedWithNoReason(); - - void SetExited(); - - Status RequestStop(); - - // --------------------------------------------------------------------- - // Private interface - // --------------------------------------------------------------------- - void MaybeLogStateChange(lldb::StateType new_state); - - NativeProcessLinux &GetProcess(); - - void SetStopped(); - - // --------------------------------------------------------------------- - // Member Variables - // --------------------------------------------------------------------- - lldb::StateType m_state; - ThreadStopInfo m_stop_info; - std::unique_ptr<NativeRegisterContextLinux> m_reg_context_up; - std::string m_stop_description; - using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; - WatchpointIndexMap m_watchpoint_index_map; - WatchpointIndexMap m_hw_break_index_map; - std::unique_ptr<SingleStepWorkaround> m_step_workaround; -}; -} // namespace process_linux -} // namespace lldb_private - -#endif // #ifndef liblldb_NativeThreadLinux_H_ diff --git a/source/Plugins/Process/Linux/ProcessorTrace.cpp b/source/Plugins/Process/Linux/ProcessorTrace.cpp deleted file mode 100644 index 505c526ab70d7..0000000000000 --- a/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ /dev/null @@ -1,395 +0,0 @@ -//===-- ProcessorTrace.cpp ------------------------------------ -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <algorithm> -#include <fstream> - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MathExtras.h" - -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "ProcessorTrace.h" -#include "lldb/Host/linux/Support.h" - -#include <sys/syscall.h> - -using namespace lldb; -using namespace lldb_private; -using namespace process_linux; -using namespace llvm; - -lldb::user_id_t ProcessorTraceMonitor::m_trace_num = 1; - -Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - Status error; - - config.setType(lldb::TraceType::eTraceTypeProcessorTrace); - config.setMetaDataBufferSize(m_mmap_meta->data_size); - - config.setTraceBufferSize(m_mmap_meta->aux_size); - - error = GetCPUType(config); - - return error; -#endif -} - -Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, - const TraceOptions &config) { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - Status error; - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - LLDB_LOG(log, "called thread id {0}", tid); - uint64_t page_size = getpagesize(); - uint64_t bufsize = config.getTraceBufferSize(); - uint64_t metabufsize = config.getMetaDataBufferSize(); - - uint64_t numpages = static_cast<uint64_t>( - llvm::PowerOf2Floor((bufsize + page_size - 1) / page_size)); - numpages = std::max<uint64_t>(1, numpages); - bufsize = page_size * numpages; - - numpages = static_cast<uint64_t>( - llvm::PowerOf2Floor((metabufsize + page_size - 1) / page_size)); - metabufsize = page_size * numpages; - - perf_event_attr attr; - memset(&attr, 0, sizeof(attr)); - attr.size = sizeof(attr); - attr.exclude_kernel = 1; - attr.sample_type = PERF_SAMPLE_TIME; - attr.sample_id_all = 1; - attr.exclude_hv = 1; - attr.exclude_idle = 1; - attr.mmap = 1; - - int intel_pt_type = 0; - - auto ret = llvm::MemoryBuffer::getFileAsStream( - "/sys/bus/event_source/devices/intel_pt/type"); - if (!ret) { - LLDB_LOG(log, "failed to open Config file"); - return ret.getError(); - } - - StringRef rest = ret.get()->getBuffer(); - if (rest.empty() || rest.trim().getAsInteger(10, intel_pt_type)) { - LLDB_LOG(log, "failed to read Config file"); - error.SetErrorString("invalid file"); - return error; - } - - rest.trim().getAsInteger(10, intel_pt_type); - LLDB_LOG(log, "intel pt type {0}", intel_pt_type); - attr.type = intel_pt_type; - - LLDB_LOG(log, "meta buffer size {0}", metabufsize); - LLDB_LOG(log, "buffer size {0} ", bufsize); - - if (error.Fail()) { - LLDB_LOG(log, "Status in custom config"); - - return error; - } - - errno = 0; - auto fd = - syscall(SYS_perf_event_open, &attr, static_cast<::tid_t>(tid), -1, -1, 0); - if (fd == -1) { - LLDB_LOG(log, "syscall error {0}", errno); - error.SetErrorString("perf event syscall Failed"); - return error; - } - - m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close()); - - errno = 0; - auto base = - mmap(NULL, (metabufsize + page_size), PROT_WRITE, MAP_SHARED, fd, 0); - - if (base == MAP_FAILED) { - LLDB_LOG(log, "mmap base error {0}", errno); - error.SetErrorString("Meta buffer allocation failed"); - return error; - } - - m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>( - reinterpret_cast<perf_event_mmap_page *>(base), - munmap_delete(metabufsize + page_size)); - - m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size; - m_mmap_meta->aux_size = bufsize; - - errno = 0; - auto mmap_aux = mmap(NULL, bufsize, PROT_READ, MAP_SHARED, fd, - static_cast<long int>(m_mmap_meta->aux_offset)); - - if (mmap_aux == MAP_FAILED) { - LLDB_LOG(log, "second mmap done {0}", errno); - error.SetErrorString("Trace buffer allocation failed"); - return error; - } - m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>( - reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(bufsize)); - return error; -#endif -} - -llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetDataBuffer() { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - return MutableArrayRef<uint8_t>( - (reinterpret_cast<uint8_t *>(m_mmap_meta.get()) + - m_mmap_meta->data_offset), - m_mmap_meta->data_size); -#endif -} - -llvm::MutableArrayRef<uint8_t> ProcessorTraceMonitor::GetAuxBuffer() { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - return MutableArrayRef<uint8_t>(m_mmap_aux.get(), m_mmap_meta->aux_size); -#endif -} - -Status ProcessorTraceMonitor::GetCPUType(TraceOptions &config) { - - Status error; - uint64_t cpu_family = -1; - uint64_t model = -1; - uint64_t stepping = -1; - std::string vendor_id; - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - auto BufferOrError = getProcFile("cpuinfo"); - if (!BufferOrError) - return BufferOrError.getError(); - - LLDB_LOG(log, "GetCPUType Function"); - - StringRef Rest = BufferOrError.get()->getBuffer(); - while (!Rest.empty()) { - StringRef Line; - std::tie(Line, Rest) = Rest.split('\n'); - - SmallVector<StringRef, 2> columns; - Line.split(columns, StringRef(":"), -1, false); - - if (columns.size() < 2) - continue; // continue searching - - columns[1] = columns[1].trim(" "); - if (columns[0].contains("cpu family") && - columns[1].getAsInteger(10, cpu_family)) - continue; - - else if (columns[0].contains("model") && columns[1].getAsInteger(10, model)) - continue; - - else if (columns[0].contains("stepping") && - columns[1].getAsInteger(10, stepping)) - continue; - - else if (columns[0].contains("vendor_id")) { - vendor_id = columns[1].str(); - if (!vendor_id.empty()) - continue; - } - LLDB_LOG(log, "{0}:{1}:{2}:{3}", cpu_family, model, stepping, vendor_id); - - if ((cpu_family != static_cast<uint64_t>(-1)) && - (model != static_cast<uint64_t>(-1)) && - (stepping != static_cast<uint64_t>(-1)) && (!vendor_id.empty())) { - auto params_dict = std::make_shared<StructuredData::Dictionary>(); - params_dict->AddIntegerItem("cpu_family", cpu_family); - params_dict->AddIntegerItem("cpu_model", model); - params_dict->AddIntegerItem("cpu_stepping", stepping); - params_dict->AddStringItem("cpu_vendor", vendor_id); - - llvm::StringRef intel_custom_params_key("intel-pt"); - - auto intel_custom_params = std::make_shared<StructuredData::Dictionary>(); - intel_custom_params->AddItem( - intel_custom_params_key, - StructuredData::ObjectSP(std::move(params_dict))); - - config.setTraceParams(intel_custom_params); - return error; // we are done - } - } - - error.SetErrorString("cpu info not found"); - return error; -} - -llvm::Expected<ProcessorTraceMonitorUP> -ProcessorTraceMonitor::Create(lldb::pid_t pid, lldb::tid_t tid, - const TraceOptions &config, - bool useProcessSettings) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - Status error; - if (tid == LLDB_INVALID_THREAD_ID) { - error.SetErrorString("thread not specified"); - return error.ToError(); - } - - ProcessorTraceMonitorUP pt_monitor_up(new ProcessorTraceMonitor); - - error = pt_monitor_up->StartTrace(pid, tid, config); - if (error.Fail()) - return error.ToError(); - - pt_monitor_up->SetThreadID(tid); - - if (useProcessSettings) { - pt_monitor_up->SetTraceID(0); - } else { - pt_monitor_up->SetTraceID(m_trace_num++); - LLDB_LOG(log, "Trace ID {0}", m_trace_num); - } - return std::move(pt_monitor_up); -} - -Status -ProcessorTraceMonitor::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - Status error; - uint64_t head = m_mmap_meta->aux_head; - - LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head); - - /** - * When configured as ring buffer, the aux buffer keeps wrapping around - * the buffer and its not possible to detect how many times the buffer - * wrapped. Initially the buffer is filled with zeros,as shown below - * so in order to get complete buffer we first copy firstpartsize, followed - * by any left over part from beginning to aux_head - * - * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size - * aux_head->||<- firstpartsize ->| - * - * */ - - ReadCyclicBuffer(buffer, GetAuxBuffer(), static_cast<size_t>(head), offset); - LLDB_LOG(log, "ReadCyclic BUffer Done"); - return error; -#endif -} - -Status -ProcessorTraceMonitor::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { -#ifndef PERF_ATTR_SIZE_VER5 - llvm_unreachable("perf event not supported"); -#else - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - uint64_t bytes_remaining = buffer.size(); - Status error; - - uint64_t head = m_mmap_meta->data_head; - - /* - * The data buffer and aux buffer have different implementations - * with respect to their definition of head pointer. In the case - * of Aux data buffer the head always wraps around the aux buffer - * and we don't need to care about it, whereas the data_head keeps - * increasing and needs to be wrapped by modulus operator - */ - - LLDB_LOG(log, "bytes_remaining - {0}", bytes_remaining); - - auto data_buffer = GetDataBuffer(); - - if (head > data_buffer.size()) { - head = head % data_buffer.size(); - LLDB_LOG(log, "Data size -{0} Head - {1}", m_mmap_meta->data_size, head); - - ReadCyclicBuffer(buffer, data_buffer, static_cast<size_t>(head), offset); - bytes_remaining -= buffer.size(); - } else { - LLDB_LOG(log, "Head - {0}", head); - if (offset >= head) { - LLDB_LOG(log, "Invalid Offset "); - error.SetErrorString("invalid offset"); - buffer = buffer.slice(buffer.size()); - return error; - } - - auto data = data_buffer.slice(offset, (head - offset)); - auto remaining = std::copy(data.begin(), data.end(), buffer.begin()); - bytes_remaining -= (remaining - buffer.begin()); - } - buffer = buffer.drop_back(bytes_remaining); - return error; -#endif -} - -void ProcessorTraceMonitor::ReadCyclicBuffer( - llvm::MutableArrayRef<uint8_t> &dst, llvm::MutableArrayRef<uint8_t> src, - size_t src_cyc_index, size_t offset) { - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); - - if (dst.empty() || src.empty()) { - dst = dst.drop_back(dst.size()); - return; - } - - if (dst.data() == nullptr || src.data() == nullptr) { - dst = dst.drop_back(dst.size()); - return; - } - - if (src_cyc_index > src.size()) { - dst = dst.drop_back(dst.size()); - return; - } - - if (offset >= src.size()) { - LLDB_LOG(log, "Too Big offset "); - dst = dst.drop_back(dst.size()); - return; - } - - llvm::SmallVector<MutableArrayRef<uint8_t>, 2> parts = { - src.slice(src_cyc_index), src.take_front(src_cyc_index)}; - - if (offset > parts[0].size()) { - parts[1] = parts[1].slice(offset - parts[0].size()); - parts[0] = parts[0].drop_back(parts[0].size()); - } else if (offset == parts[0].size()) { - parts[0] = parts[0].drop_back(parts[0].size()); - } else { - parts[0] = parts[0].slice(offset); - } - auto next = dst.begin(); - auto bytes_left = dst.size(); - for (auto part : parts) { - size_t chunk_size = std::min(part.size(), bytes_left); - next = std::copy_n(part.begin(), chunk_size, next); - bytes_left -= chunk_size; - } - dst = dst.drop_back(bytes_left); -} diff --git a/source/Plugins/Process/Linux/ProcessorTrace.h b/source/Plugins/Process/Linux/ProcessorTrace.h deleted file mode 100644 index 6fd918c2bb58a..0000000000000 --- a/source/Plugins/Process/Linux/ProcessorTrace.h +++ /dev/null @@ -1,141 +0,0 @@ -//===-- ProcessorTrace.h -------------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessorTrace_H_ -#define liblldb_ProcessorTrace_H_ - -#include "lldb/Utility/Status.h" -#include "lldb/Utility/TraceOptions.h" -#include "lldb/lldb-types.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" - -#include <linux/perf_event.h> -#include <sys/mman.h> -#include <unistd.h> - -namespace lldb_private { - -namespace process_linux { - -// --------------------------------------------------------------------- -// This class keeps track of one tracing instance of -// Intel(R) Processor Trace on Linux OS. There is a map keeping track -// of different tracing instances on each thread, which enables trace -// gathering on a per thread level. -// -// The tracing instance is linked with a trace id. The trace id acts like -// a key to the tracing instance and trace manipulations could be -// performed using the trace id. -// -// The trace id could map to trace instances for a group of threads -// (spanning to all the threads in the process) or a single thread. -// The kernel interface for us is the perf_event_open. -// --------------------------------------------------------------------- - -class ProcessorTraceMonitor; -typedef std::unique_ptr<ProcessorTraceMonitor> ProcessorTraceMonitorUP; - -class ProcessorTraceMonitor { - - class munmap_delete { - size_t m_length; - - public: - munmap_delete(size_t length) : m_length(length) {} - void operator()(void *ptr) { - if (m_length) - munmap(ptr, m_length); - } - }; - - class file_close { - - public: - file_close() = default; - void operator()(int *ptr) { - if (ptr == nullptr) - return; - if (*ptr == -1) - return; - close(*ptr); - std::default_delete<int>()(ptr); - } - }; - - std::unique_ptr<perf_event_mmap_page, munmap_delete> m_mmap_meta; - std::unique_ptr<uint8_t, munmap_delete> m_mmap_aux; - std::unique_ptr<int, file_close> m_fd; - - // perf_event_mmap_page *m_mmap_base; - lldb::user_id_t m_traceid; - lldb::tid_t m_thread_id; - - // Counter to track trace instances. - static lldb::user_id_t m_trace_num; - - void SetTraceID(lldb::user_id_t traceid) { m_traceid = traceid; } - - Status StartTrace(lldb::pid_t pid, lldb::tid_t tid, - const TraceOptions &config); - - llvm::MutableArrayRef<uint8_t> GetAuxBuffer(); - llvm::MutableArrayRef<uint8_t> GetDataBuffer(); - - ProcessorTraceMonitor() - : m_mmap_meta(nullptr, munmap_delete(0)), - m_mmap_aux(nullptr, munmap_delete(0)), m_fd(nullptr, file_close()), - m_traceid(LLDB_INVALID_UID), m_thread_id(LLDB_INVALID_THREAD_ID){}; - - void SetThreadID(lldb::tid_t tid) { m_thread_id = tid; } - -public: - static Status GetCPUType(TraceOptions &config); - - static llvm::Expected<ProcessorTraceMonitorUP> - Create(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config, - bool useProcessSettings); - - Status ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0); - - Status ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0); - - ~ProcessorTraceMonitor() = default; - - lldb::tid_t GetThreadID() const { return m_thread_id; } - - lldb::user_id_t GetTraceID() const { return m_traceid; } - - Status GetTraceConfig(TraceOptions &config) const; - - // --------------------------------------------------------------------- - /// Read data from a cyclic buffer - /// - /// @param[in] [out] buf - /// Destination buffer, the buffer will be truncated to written size. - /// - /// @param[in] src - /// Source buffer which must be a cyclic buffer. - /// - /// @param[in] src_cyc_index - /// The index pointer (start of the valid data in the cyclic - /// buffer). - /// - /// @param[in] offset - /// The offset to begin reading the data in the cyclic buffer. - // --------------------------------------------------------------------- - static void ReadCyclicBuffer(llvm::MutableArrayRef<uint8_t> &dst, - llvm::MutableArrayRef<uint8_t> src, - size_t src_cyc_index, size_t offset); -}; -} // namespace process_linux -} // namespace lldb_private -#endif diff --git a/source/Plugins/Process/Linux/Procfs.h b/source/Plugins/Process/Linux/Procfs.h deleted file mode 100644 index 1d9c9dbe273fd..0000000000000 --- a/source/Plugins/Process/Linux/Procfs.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- Procfs.h ---------------------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// source/Plugins/Process/Linux/Procfs.h defines the symbols we need from -// sys/procfs.h on Android/Linux for all supported architectures. - -#include <sys/ptrace.h> - -#ifdef __ANDROID__ -#if defined(__arm64__) || defined(__aarch64__) -typedef unsigned long elf_greg_t; -typedef elf_greg_t - elf_gregset_t[(sizeof(struct user_pt_regs) / sizeof(elf_greg_t))]; -typedef struct user_fpsimd_state elf_fpregset_t; -#ifndef NT_FPREGSET -#define NT_FPREGSET NT_PRFPREG -#endif // NT_FPREGSET -#elif defined(__mips__) -#ifndef NT_FPREGSET -#define NT_FPREGSET NT_PRFPREG -#endif // NT_FPREGSET -#endif -#else // __ANDROID__ -#include <sys/procfs.h> -#endif // __ANDROID__ diff --git a/source/Plugins/Process/Linux/SingleStepCheck.cpp b/source/Plugins/Process/Linux/SingleStepCheck.cpp deleted file mode 100644 index c57a2daf22757..0000000000000 --- a/source/Plugins/Process/Linux/SingleStepCheck.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//===-- SingleStepCheck.cpp ----------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "SingleStepCheck.h" - -#include <sched.h> -#include <signal.h> -#include <sys/wait.h> -#include <unistd.h> - -#include "NativeProcessLinux.h" - -#include "llvm/Support/Compiler.h" - -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "lldb/Host/linux/Ptrace.h" -#include "lldb/Utility/Status.h" - -using namespace lldb; -using namespace lldb_private; -using namespace lldb_private::process_linux; - -#if defined(__arm64__) || defined(__aarch64__) -namespace { - -void LLVM_ATTRIBUTE_NORETURN Child() { - if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) - _exit(1); - - // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer - // will fiddle with our cpu affinities and monitor the behaviour. - for (;;) { - raise(SIGSTOP); - - // Generate a bunch of instructions here, so that a single-step does not - // land in the raise() accidentally. If single-stepping works, we will be - // spinning in this loop. If it doesn't, we'll land in the raise() call - // above. - for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i) - ; - } -} - -struct ChildDeleter { - ::pid_t pid; - - ~ChildDeleter() { - int status; - kill(pid, SIGKILL); // Kill the child. - waitpid(pid, &status, __WALL); // Pick up the remains. - } -}; - -bool WorkaroundNeeded() { - // We shall spawn a child, and use it to verify the debug capabilities of the - // cpu. We shall iterate through the cpus, bind the child to each one in - // turn, and verify that single-stepping works on that cpu. A workaround is - // needed if we find at least one broken cpu. - - Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - ::pid_t child_pid = fork(); - if (child_pid == -1) { - LLDB_LOG(log, "failed to fork(): {0}", Status(errno, eErrorTypePOSIX)); - return false; - } - if (child_pid == 0) - Child(); - - ChildDeleter child_deleter{child_pid}; - cpu_set_t available_cpus; - if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == - -1) { - LLDB_LOG(log, "failed to get available cpus: {0}", - Status(errno, eErrorTypePOSIX)); - return false; - } - - int status; - ::pid_t wpid = waitpid(child_pid, &status, __WALL); - if (wpid != child_pid || !WIFSTOPPED(status)) { - LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status, - Status(errno, eErrorTypePOSIX)); - return false; - } - - unsigned cpu; - for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) { - if (!CPU_ISSET(cpu, &available_cpus)) - continue; - - cpu_set_t cpus; - CPU_ZERO(&cpus); - CPU_SET(cpu, &cpus); - if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) { - LLDB_LOG(log, "failed to switch to cpu {0}: {1}", cpu, - Status(errno, eErrorTypePOSIX)); - continue; - } - - int status; - Status error = - NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); - if (error.Fail()) { - LLDB_LOG(log, "single step failed: {0}", error); - break; - } - - wpid = waitpid(child_pid, &status, __WALL); - if (wpid != child_pid || !WIFSTOPPED(status)) { - LLDB_LOG(log, "waitpid() failed (status = {0:x}): {1}", status, - Status(errno, eErrorTypePOSIX)); - break; - } - if (WSTOPSIG(status) != SIGTRAP) { - LLDB_LOG(log, "single stepping on cpu {0} failed with status {1:x}", cpu, - status); - break; - } - } - - // cpu is either the index of the first broken cpu, or CPU_SETSIZE. - if (cpu == 0) { - LLDB_LOG(log, - "SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING " - "LIKELY TO BE UNRELIABLE."); - // No point in trying to fiddle with the affinities, just give it our best - // shot and see how it goes. - return false; - } - - return cpu != CPU_SETSIZE; -} - -} // end anonymous namespace - -std::unique_ptr<SingleStepWorkaround> SingleStepWorkaround::Get(::pid_t tid) { - Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - - static bool workaround_needed = WorkaroundNeeded(); - if (!workaround_needed) { - LLDB_LOG(log, "workaround for thread {0} not needed", tid); - return nullptr; - } - - cpu_set_t original_set; - if (sched_getaffinity(tid, sizeof original_set, &original_set) != 0) { - // This should really not fail. But, just in case... - LLDB_LOG(log, "Unable to get cpu affinity for thread {0}: {1}", tid, - Status(errno, eErrorTypePOSIX)); - return nullptr; - } - - cpu_set_t set; - CPU_ZERO(&set); - CPU_SET(0, &set); - if (sched_setaffinity(tid, sizeof set, &set) != 0) { - // This may fail in very locked down systems, if the thread is not allowed - // to run on cpu 0. If that happens, only thing we can do is it log it and - // continue... - LLDB_LOG(log, "Unable to set cpu affinity for thread {0}: {1}", tid, - Status(errno, eErrorTypePOSIX)); - } - - LLDB_LOG(log, "workaround for thread {0} prepared", tid); - return llvm::make_unique<SingleStepWorkaround>(tid, original_set); -} - -SingleStepWorkaround::~SingleStepWorkaround() { - Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD); - LLDB_LOG(log, "Removing workaround"); - if (sched_setaffinity(m_tid, sizeof m_original_set, &m_original_set) != 0) { - LLDB_LOG(log, "Unable to reset cpu affinity for thread {0}: {1}", m_tid, - Status(errno, eErrorTypePOSIX)); - } -} -#endif diff --git a/source/Plugins/Process/Linux/SingleStepCheck.h b/source/Plugins/Process/Linux/SingleStepCheck.h deleted file mode 100644 index afeda7310349a..0000000000000 --- a/source/Plugins/Process/Linux/SingleStepCheck.h +++ /dev/null @@ -1,57 +0,0 @@ -//===-- SingleStepCheck.h ------------------------------------- -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_SingleStepCheck_H_ -#define liblldb_SingleStepCheck_H_ - -#include <memory> -#include <sched.h> -#include <sys/types.h> - -namespace lldb_private { -namespace process_linux { - -// arm64 linux had a bug which prevented single-stepping and watchpoints from -// working on non-boot cpus, due to them being incorrectly initialized after -// coming out of suspend. This issue is particularly affecting android M, which -// uses suspend ("doze mode") quite aggressively. This code detects that -// situation and makes single-stepping work by doing all the step operations on -// the boot cpu. -// -// The underlying issue has been fixed in android N and linux 4.4. This code can -// be removed once these systems become obsolete. - -#if defined(__arm64__) || defined(__aarch64__) -class SingleStepWorkaround { - ::pid_t m_tid; - cpu_set_t m_original_set; - - SingleStepWorkaround(const SingleStepWorkaround &) = delete; - void operator=(const SingleStepWorkaround &) = delete; - -public: - SingleStepWorkaround(::pid_t tid, cpu_set_t original_set) - : m_tid(tid), m_original_set(original_set) {} - ~SingleStepWorkaround(); - - static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid); -}; -#else -class SingleStepWorkaround { -public: - static std::unique_ptr<SingleStepWorkaround> Get(::pid_t tid) { - return nullptr; - } -}; -#endif - -} // end namespace process_linux -} // end namespace lldb_private - -#endif // #ifndef liblldb_SingleStepCheck_H_ diff --git a/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt b/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt deleted file mode 100644 index bed0e3b7ab377..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -add_lldb_library(lldbPluginProcessMacOSXKernel PLUGIN - CommunicationKDP.cpp - ProcessKDP.cpp - ProcessKDPLog.cpp - RegisterContextKDP_arm.cpp - RegisterContextKDP_arm64.cpp - RegisterContextKDP_i386.cpp - RegisterContextKDP_x86_64.cpp - ThreadKDP.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginDynamicLoaderDarwinKernel - lldbPluginDynamicLoaderStatic - lldbPluginProcessUtility - ) diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp deleted file mode 100644 index 8908108eff4bd..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ /dev/null @@ -1,1289 +0,0 @@ -//===-- CommunicationKDP.cpp ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "CommunicationKDP.h" - -#include <errno.h> -#include <limits.h> -#include <string.h> - - -#include "lldb/Core/DumpDataExtractor.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/UUID.h" - -#include "ProcessKDPLog.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// CommunicationKDP constructor -//---------------------------------------------------------------------- -CommunicationKDP::CommunicationKDP(const char *comm_name) - : Communication(comm_name), m_addr_byte_size(4), - m_byte_order(eByteOrderLittle), m_packet_timeout(5), m_sequence_mutex(), - m_is_running(false), m_session_key(0u), m_request_sequence_id(0u), - m_exception_sequence_id(0u), m_kdp_version_version(0u), - m_kdp_version_feature(0u), m_kdp_hostinfo_cpu_mask(0u), - m_kdp_hostinfo_cpu_type(0u), m_kdp_hostinfo_cpu_subtype(0u) {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -CommunicationKDP::~CommunicationKDP() { - if (IsConnected()) { - Disconnect(); - } -} - -bool CommunicationKDP::SendRequestPacket( - const PacketStreamType &request_packet) { - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return SendRequestPacketNoLock(request_packet); -} - -void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type, - PacketStreamType &request_packet, - uint16_t request_length) { - request_packet.Clear(); - request_packet.PutHex8(request_type | - ePacketTypeRequest); // Set the request type - request_packet.PutHex8(m_request_sequence_id++); // Sequence number - request_packet.PutHex16( - request_length); // Length of the packet including this header - request_packet.PutHex32(m_session_key); // Session key -} - -bool CommunicationKDP::SendRequestAndGetReply( - const CommandType command, const PacketStreamType &request_packet, - DataExtractor &reply_packet) { - if (IsRunning()) { - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - if (log) { - PacketStreamType log_strm; - DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize()); - log->Printf("error: kdp running, not sending packet: %.*s", - (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return false; - } - - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); -#ifdef LLDB_CONFIGURATION_DEBUG - // NOTE: this only works for packets that are in native endian byte order - assert(request_packet.GetSize() == - *((const uint16_t *)(request_packet.GetData() + 2))); -#endif - lldb::offset_t offset = 1; - const uint32_t num_retries = 3; - for (uint32_t i = 0; i < num_retries; ++i) { - if (SendRequestPacketNoLock(request_packet)) { - const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; - while (1) { - if (WaitForPacketWithTimeoutMicroSecondsNoLock( - reply_packet, - std::chrono::microseconds(GetPacketTimeout()).count())) { - offset = 0; - const uint8_t reply_command = reply_packet.GetU8(&offset); - const uint8_t reply_sequence_id = reply_packet.GetU8(&offset); - if (request_sequence_id == reply_sequence_id) { - // The sequent ID was correct, now verify we got the response we - // were looking for - if ((reply_command & eCommandTypeMask) == command) { - // Success - if (command == KDP_RESUMECPUS) - m_is_running.SetValue(true, eBroadcastAlways); - return true; - } else { - // Failed to get the correct response, bail - reply_packet.Clear(); - return false; - } - } else if (reply_sequence_id > request_sequence_id) { - // Sequence ID was greater than the sequence ID of the packet we - // sent, something is really wrong... - reply_packet.Clear(); - return false; - } else { - // The reply sequence ID was less than our current packet's - // sequence ID so we should keep trying to get a response because - // this was a response for a previous packet that we must have - // retried. - } - } else { - // Break and retry sending the packet as we didn't get a response due - // to timeout - break; - } - } - } - } - reply_packet.Clear(); - return false; -} - -bool CommunicationKDP::SendRequestPacketNoLock( - const PacketStreamType &request_packet) { - if (IsConnected()) { - const char *packet_data = request_packet.GetData(); - const size_t packet_size = request_packet.GetSize(); - - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - if (log) { - PacketStreamType log_strm; - DumpPacket(log_strm, packet_data, packet_size); - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - ConnectionStatus status = eConnectionStatusSuccess; - - size_t bytes_written = Write(packet_data, packet_size, status, NULL); - - if (bytes_written == packet_size) - return true; - - if (log) - log->Printf("error: failed to send packet entire packet %" PRIu64 - " of %" PRIu64 " bytes sent", - (uint64_t)bytes_written, (uint64_t)packet_size); - } - return false; -} - -bool CommunicationKDP::GetSequenceMutex( - std::unique_lock<std::recursive_mutex> &lock) { - return (lock = std::unique_lock<std::recursive_mutex>(m_sequence_mutex, - std::try_to_lock)) - .owns_lock(); -} - -bool CommunicationKDP::WaitForNotRunningPrivate( - const std::chrono::microseconds &timeout) { - return m_is_running.WaitForValueEqualTo(false, timeout); -} - -size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds(DataExtractor &packet, - uint32_t timeout_usec) { - std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); - return WaitForPacketWithTimeoutMicroSecondsNoLock(packet, timeout_usec); -} - -size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( - DataExtractor &packet, uint32_t timeout_usec) { - uint8_t buffer[8192]; - Status error; - - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - - // Check for a packet from our cache first without trying any reading... - if (CheckForPacket(NULL, 0, packet)) - return packet.GetByteSize(); - - bool timed_out = false; - while (IsConnected() && !timed_out) { - lldb::ConnectionStatus status = eConnectionStatusNoConnection; - size_t bytes_read = Read(buffer, sizeof(buffer), - timeout_usec == UINT32_MAX - ? Timeout<std::micro>(llvm::None) - : std::chrono::microseconds(timeout_usec), - status, &error); - - LLDB_LOGV(log, - "Read (buffer, sizeof(buffer), timeout_usec = 0x{0:x}, " - "status = {1}, error = {2}) => bytes_read = {4}", - timeout_usec, - Communication::ConnectionStatusAsCString(status), - error, bytes_read); - - if (bytes_read > 0) { - if (CheckForPacket(buffer, bytes_read, packet)) - return packet.GetByteSize(); - } else { - switch (status) { - case eConnectionStatusInterrupted: - case eConnectionStatusTimedOut: - timed_out = true; - break; - case eConnectionStatusSuccess: - // printf ("status = success but error = %s\n", - // error.AsCString("<invalid>")); - break; - - case eConnectionStatusEndOfFile: - case eConnectionStatusNoConnection: - case eConnectionStatusLostConnection: - case eConnectionStatusError: - Disconnect(); - break; - } - } - } - packet.Clear(); - return 0; -} - -bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len, - DataExtractor &packet) { - // Put the packet data into the buffer in a thread safe fashion - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); - - if (src && src_len > 0) { - if (log && log->GetVerbose()) { - PacketStreamType log_strm; - DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); - log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, - (uint32_t)src_len, log_strm.GetData()); - } - m_bytes.append((const char *)src, src_len); - } - - // Make sure we at least have enough bytes for a packet header - const size_t bytes_available = m_bytes.size(); - if (bytes_available >= 8) { - packet.SetData(&m_bytes[0], bytes_available, m_byte_order); - lldb::offset_t offset = 0; - uint8_t reply_command = packet.GetU8(&offset); - switch (reply_command) { - case ePacketTypeRequest | KDP_EXCEPTION: - case ePacketTypeRequest | KDP_TERMINATION: - // We got an exception request, so be sure to send an ACK - { - PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - // Set the reply but and make the ACK packet - request_ack_packet.PutHex8(reply_command | ePacketTypeReply); - request_ack_packet.PutHex8(packet.GetU8(&offset)); - request_ack_packet.PutHex16(packet.GetU16(&offset)); - request_ack_packet.PutHex32(packet.GetU32(&offset)); - m_is_running.SetValue(false, eBroadcastAlways); - // Ack to the exception or termination - SendRequestPacketNoLock(request_ack_packet); - } - // Fall through to case below to get packet contents - LLVM_FALLTHROUGH; - case ePacketTypeReply | KDP_CONNECT: - case ePacketTypeReply | KDP_DISCONNECT: - case ePacketTypeReply | KDP_HOSTINFO: - case ePacketTypeReply | KDP_VERSION: - case ePacketTypeReply | KDP_MAXBYTES: - case ePacketTypeReply | KDP_READMEM: - case ePacketTypeReply | KDP_WRITEMEM: - case ePacketTypeReply | KDP_READREGS: - case ePacketTypeReply | KDP_WRITEREGS: - case ePacketTypeReply | KDP_LOAD: - case ePacketTypeReply | KDP_IMAGEPATH: - case ePacketTypeReply | KDP_SUSPEND: - case ePacketTypeReply | KDP_RESUMECPUS: - case ePacketTypeReply | KDP_BREAKPOINT_SET: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: - case ePacketTypeReply | KDP_REGIONS: - case ePacketTypeReply | KDP_REATTACH: - case ePacketTypeReply | KDP_HOSTREBOOT: - case ePacketTypeReply | KDP_READMEM64: - case ePacketTypeReply | KDP_WRITEMEM64: - case ePacketTypeReply | KDP_BREAKPOINT_SET64: - case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: - case ePacketTypeReply | KDP_KERNELVERSION: - case ePacketTypeReply | KDP_READPHYSMEM64: - case ePacketTypeReply | KDP_WRITEPHYSMEM64: - case ePacketTypeReply | KDP_READIOPORT: - case ePacketTypeReply | KDP_WRITEIOPORT: - case ePacketTypeReply | KDP_READMSR64: - case ePacketTypeReply | KDP_WRITEMSR64: - case ePacketTypeReply | KDP_DUMPINFO: { - offset = 2; - const uint16_t length = packet.GetU16(&offset); - if (length <= bytes_available) { - // We have an entire packet ready, we need to copy the data bytes into - // a buffer that will be owned by the packet and erase the bytes from - // our communcation buffer "m_bytes" - packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length))); - m_bytes.erase(0, length); - - if (log) { - PacketStreamType log_strm; - DumpPacket(log_strm, packet); - - log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); - } - return true; - } - } break; - - default: - // Unrecognized reply command byte, erase this byte and try to get back - // on track - if (log) - log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", - __FUNCTION__, (uint8_t)m_bytes[0]); - m_bytes.erase(0, 1); - break; - } - } - packet.Clear(); - return false; -} - -bool CommunicationKDP::SendRequestConnect(uint16_t reply_port, - uint16_t exc_port, - const char *greeting) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - if (greeting == NULL) - greeting = ""; - - const CommandType command = KDP_CONNECT; - // Length is 82 uint16_t and the length of the greeting C string with the - // terminating NULL - const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; - MakeRequestPacketHeader(command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder(eByteOrderLittle); - request_packet.PutHex16(htons(reply_port)); - request_packet.PutHex16(htons(exc_port)); - request_packet.SetByteOrder(m_byte_order); - request_packet.PutCString(greeting); - DataExtractor reply_packet; - return SendRequestAndGetReply(command, request_packet, reply_packet); -} - -void CommunicationKDP::ClearKDPSettings() { - m_request_sequence_id = 0; - m_kdp_version_version = 0; - m_kdp_version_feature = 0; - m_kdp_hostinfo_cpu_mask = 0; - m_kdp_hostinfo_cpu_type = 0; - m_kdp_hostinfo_cpu_subtype = 0; -} - -bool CommunicationKDP::SendRequestReattach(uint16_t reply_port) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_REATTACH; - // Length is 8 bytes for the header plus 2 bytes for the reply UDP port - const uint32_t command_length = 8 + 2; - MakeRequestPacketHeader(command, request_packet, command_length); - // Always send connect ports as little endian - request_packet.SetByteOrder(eByteOrderLittle); - request_packet.PutHex16(htons(reply_port)); - request_packet.SetByteOrder(m_byte_order); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - // Reset the sequence ID to zero for reattach - ClearKDPSettings(); - lldb::offset_t offset = 4; - m_session_key = reply_packet.GetU32(&offset); - return true; - } - return false; -} - -uint32_t CommunicationKDP::GetVersion() { - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_version; -} - -uint32_t CommunicationKDP::GetFeatureFlags() { - if (!VersionIsValid()) - SendRequestVersion(); - return m_kdp_version_feature; -} - -bool CommunicationKDP::SendRequestVersion() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_VERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader(command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - m_kdp_version_version = reply_packet.GetU32(&offset); - m_kdp_version_feature = reply_packet.GetU32(&offset); - return true; - } - return false; -} - -uint32_t CommunicationKDP::GetCPUMask() { - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_mask; -} - -uint32_t CommunicationKDP::GetCPUType() { - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_type; -} - -uint32_t CommunicationKDP::GetCPUSubtype() { - if (!HostInfoIsValid()) - SendRequestHostInfo(); - return m_kdp_hostinfo_cpu_subtype; -} - -lldb_private::UUID CommunicationKDP::GetUUID() { - UUID uuid; - if (GetKernelVersion() == NULL) - return uuid; - - if (m_kernel_version.find("UUID=") == std::string::npos) - return uuid; - - size_t p = m_kernel_version.find("UUID=") + strlen("UUID="); - std::string uuid_str = m_kernel_version.substr(p, 36); - if (uuid_str.size() < 32) - return uuid; - - if (uuid.SetFromStringRef(uuid_str) == 0) { - UUID invalid_uuid; - return invalid_uuid; - } - - return uuid; -} - -bool CommunicationKDP::RemoteIsEFI() { - if (GetKernelVersion() == NULL) - return false; - return strncmp(m_kernel_version.c_str(), "EFI", 3) == 0; -} - -bool CommunicationKDP::RemoteIsDarwinKernel() { - if (GetKernelVersion() == NULL) - return false; - return m_kernel_version.find("Darwin Kernel") != std::string::npos; -} - -lldb::addr_t CommunicationKDP::GetLoadAddress() { - if (GetKernelVersion() == NULL) - return LLDB_INVALID_ADDRESS; - - if (m_kernel_version.find("stext=") == std::string::npos) - return LLDB_INVALID_ADDRESS; - size_t p = m_kernel_version.find("stext=") + strlen("stext="); - if (m_kernel_version[p] != '0' || m_kernel_version[p + 1] != 'x') - return LLDB_INVALID_ADDRESS; - - addr_t kernel_load_address; - errno = 0; - kernel_load_address = ::strtoul(m_kernel_version.c_str() + p, NULL, 16); - if (errno != 0 || kernel_load_address == 0) - return LLDB_INVALID_ADDRESS; - - return kernel_load_address; -} - -bool CommunicationKDP::SendRequestHostInfo() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_HOSTINFO; - const uint32_t command_length = 8; - MakeRequestPacketHeader(command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - m_kdp_hostinfo_cpu_mask = reply_packet.GetU32(&offset); - m_kdp_hostinfo_cpu_type = reply_packet.GetU32(&offset); - m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32(&offset); - - ArchSpec kernel_arch; - kernel_arch.SetArchitecture(eArchTypeMachO, m_kdp_hostinfo_cpu_type, - m_kdp_hostinfo_cpu_subtype); - - m_addr_byte_size = kernel_arch.GetAddressByteSize(); - m_byte_order = kernel_arch.GetByteOrder(); - return true; - } - return false; -} - -const char *CommunicationKDP::GetKernelVersion() { - if (m_kernel_version.empty()) - SendRequestKernelVersion(); - return m_kernel_version.c_str(); -} - -bool CommunicationKDP::SendRequestKernelVersion() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_KERNELVERSION; - const uint32_t command_length = 8; - MakeRequestPacketHeader(command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - const char *kernel_version_cstr = reply_packet.PeekCStr(8); - if (kernel_version_cstr && kernel_version_cstr[0]) - m_kernel_version.assign(kernel_version_cstr); - return true; - } - return false; -} - -bool CommunicationKDP::SendRequestDisconnect() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_DISCONNECT; - const uint32_t command_length = 8; - MakeRequestPacketHeader(command, request_packet, command_length); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - // Are we supposed to get a reply for disconnect? - } - ClearKDPSettings(); - return true; -} - -uint32_t CommunicationKDP::SendRequestReadMemory(lldb::addr_t addr, void *dst, - uint32_t dst_len, - Status &error) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_READMEM64 : KDP_READMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutMaxHex64(addr, command_addr_byte_size); - request_packet.PutHex32(dst_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) { - const void *src = reply_packet.GetData(&offset, src_len); - if (src) { - ::memcpy(dst, src, src_len); - error.Clear(); - return src_len; - } - } - if (kdp_error) - error.SetErrorStringWithFormat("kdp read memory failed (error %u)", - kdp_error); - else - error.SetErrorString("kdp read memory failed"); - } else { - error.SetErrorString("failed to send packet"); - } - return 0; -} - -uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr, - const void *src, - uint32_t src_len, - Status &error) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutMaxHex64(addr, command_addr_byte_size); - request_packet.PutHex32(src_len); - request_packet.PutRawBytes(src, src_len); - - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - if (kdp_error) - error.SetErrorStringWithFormat("kdp write memory failed (error %u)", - kdp_error); - else { - error.Clear(); - return src_len; - } - } else { - error.SetErrorString("failed to send packet"); - } - return 0; -} - -bool CommunicationKDP::SendRawRequest( - uint8_t command_byte, - const void *src, // Raw packet payload bytes - uint32_t src_len, // Raw packet payload length - DataExtractor &reply_packet, Status &error) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - // Size is header + address size + uint32_t length - const uint32_t command_length = 8 + src_len; - const CommandType command = (CommandType)command_byte; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutRawBytes(src, src_len); - - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - if (kdp_error && (command_byte != KDP_DUMPINFO)) - error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)", - command_byte, kdp_error); - else { - error.Clear(); - return true; - } - } else { - error.SetErrorString("failed to send packet"); - } - return false; -} - -const char *CommunicationKDP::GetCommandAsCString(uint8_t command) { - switch (command) { - case KDP_CONNECT: - return "KDP_CONNECT"; - case KDP_DISCONNECT: - return "KDP_DISCONNECT"; - case KDP_HOSTINFO: - return "KDP_HOSTINFO"; - case KDP_VERSION: - return "KDP_VERSION"; - case KDP_MAXBYTES: - return "KDP_MAXBYTES"; - case KDP_READMEM: - return "KDP_READMEM"; - case KDP_WRITEMEM: - return "KDP_WRITEMEM"; - case KDP_READREGS: - return "KDP_READREGS"; - case KDP_WRITEREGS: - return "KDP_WRITEREGS"; - case KDP_LOAD: - return "KDP_LOAD"; - case KDP_IMAGEPATH: - return "KDP_IMAGEPATH"; - case KDP_SUSPEND: - return "KDP_SUSPEND"; - case KDP_RESUMECPUS: - return "KDP_RESUMECPUS"; - case KDP_EXCEPTION: - return "KDP_EXCEPTION"; - case KDP_TERMINATION: - return "KDP_TERMINATION"; - case KDP_BREAKPOINT_SET: - return "KDP_BREAKPOINT_SET"; - case KDP_BREAKPOINT_REMOVE: - return "KDP_BREAKPOINT_REMOVE"; - case KDP_REGIONS: - return "KDP_REGIONS"; - case KDP_REATTACH: - return "KDP_REATTACH"; - case KDP_HOSTREBOOT: - return "KDP_HOSTREBOOT"; - case KDP_READMEM64: - return "KDP_READMEM64"; - case KDP_WRITEMEM64: - return "KDP_WRITEMEM64"; - case KDP_BREAKPOINT_SET64: - return "KDP_BREAKPOINT64_SET"; - case KDP_BREAKPOINT_REMOVE64: - return "KDP_BREAKPOINT64_REMOVE"; - case KDP_KERNELVERSION: - return "KDP_KERNELVERSION"; - case KDP_READPHYSMEM64: - return "KDP_READPHYSMEM64"; - case KDP_WRITEPHYSMEM64: - return "KDP_WRITEPHYSMEM64"; - case KDP_READIOPORT: - return "KDP_READIOPORT"; - case KDP_WRITEIOPORT: - return "KDP_WRITEIOPORT"; - case KDP_READMSR64: - return "KDP_READMSR64"; - case KDP_WRITEMSR64: - return "KDP_WRITEMSR64"; - case KDP_DUMPINFO: - return "KDP_DUMPINFO"; - } - return NULL; -} - -void CommunicationKDP::DumpPacket(Stream &s, const void *data, - uint32_t data_len) { - DataExtractor extractor(data, data_len, m_byte_order, m_addr_byte_size); - DumpPacket(s, extractor); -} - -void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { - const char *error_desc = NULL; - if (packet.GetByteSize() < 8) { - error_desc = "error: invalid packet (too short): "; - } else { - lldb::offset_t offset = 0; - const uint8_t first_packet_byte = packet.GetU8(&offset); - const uint8_t sequence_id = packet.GetU8(&offset); - const uint16_t length = packet.GetU16(&offset); - const uint32_t key = packet.GetU32(&offset); - const CommandType command = ExtractCommand(first_packet_byte); - const char *command_name = GetCommandAsCString(command); - if (command_name) { - const bool is_reply = ExtractIsReply(first_packet_byte); - s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", - IsRunning(), is_reply ? "<--" : "-->", command_name, - first_packet_byte, sequence_id, length, key); - - if (is_reply) { - // Dump request reply packets - switch (command) { - // Commands that return a single 32 bit error - case KDP_CONNECT: - case KDP_WRITEMEM: - case KDP_WRITEMEM64: - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: - case KDP_WRITEREGS: - case KDP_LOAD: - case KDP_WRITEIOPORT: - case KDP_WRITEMSR64: { - const uint32_t error = packet.GetU32(&offset); - s.Printf(" (error=0x%8.8x)", error); - } break; - - case KDP_DISCONNECT: - case KDP_REATTACH: - case KDP_HOSTREBOOT: - case KDP_SUSPEND: - case KDP_RESUMECPUS: - case KDP_EXCEPTION: - case KDP_TERMINATION: - // No return value for the reply, just the header to ack - s.PutCString(" ()"); - break; - - case KDP_HOSTINFO: { - const uint32_t cpu_mask = packet.GetU32(&offset); - const uint32_t cpu_type = packet.GetU32(&offset); - const uint32_t cpu_subtype = packet.GetU32(&offset); - s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", - cpu_mask, cpu_type, cpu_subtype); - } break; - - case KDP_VERSION: { - const uint32_t version = packet.GetU32(&offset); - const uint32_t feature = packet.GetU32(&offset); - s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); - } break; - - case KDP_REGIONS: { - const uint32_t region_count = packet.GetU32(&offset); - s.Printf(" (count = %u", region_count); - for (uint32_t i = 0; i < region_count; ++i) { - const addr_t region_addr = packet.GetPointer(&offset); - const uint32_t region_size = packet.GetU32(&offset); - const uint32_t region_prot = packet.GetU32(&offset); - s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 - " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", - region_addr, region_addr, region_addr + region_size, - region_size, GetPermissionsAsCString(region_prot)); - } - } break; - - case KDP_READMEM: - case KDP_READMEM64: - case KDP_READPHYSMEM64: { - const uint32_t error = packet.GetU32(&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x:\n", error); - if (count > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatBytesWithASCII, // Format to use - 1, // Size of each item - // in bytes - count, // Number of items - 16, // Number per line - m_last_read_memory_addr, // Don't show addresses - // before each line - 0, 0); // No bitfields - } break; - - case KDP_READREGS: { - const uint32_t error = packet.GetU32(&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x regs:\n", error); - if (count > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item - // in bytes - count / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, - // Don't - // show addresses before - // each line - 0, 0); // No bitfields - } break; - - case KDP_KERNELVERSION: { - const char *kernel_version = packet.PeekCStr(8); - s.Printf(" (version = \"%s\")", kernel_version); - } break; - - case KDP_MAXBYTES: { - const uint32_t max_bytes = packet.GetU32(&offset); - s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); - } break; - case KDP_IMAGEPATH: { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } break; - - case KDP_READIOPORT: - case KDP_READMSR64: { - const uint32_t error = packet.GetU32(&offset); - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (error = 0x%8.8x io:\n", error); - if (count > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses - // before each line - 0, 0); // No bitfields - } break; - case KDP_DUMPINFO: { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in - // bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses - // before each line - 0, 0); // No bitfields - - } break; - - default: - s.Printf(" (add support for dumping this packet reply!!!"); - break; - } - } else { - // Dump request packets - switch (command) { - case KDP_CONNECT: { - const uint16_t reply_port = ntohs(packet.GetU16(&offset)); - const uint16_t exc_port = ntohs(packet.GetU16(&offset)); - s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", - reply_port, exc_port, packet.GetCStr(&offset)); - } break; - - case KDP_DISCONNECT: - case KDP_HOSTREBOOT: - case KDP_HOSTINFO: - case KDP_VERSION: - case KDP_REGIONS: - case KDP_KERNELVERSION: - case KDP_MAXBYTES: - case KDP_IMAGEPATH: - case KDP_SUSPEND: - // No args, just the header in the request... - s.PutCString(" ()"); - break; - - case KDP_RESUMECPUS: { - const uint32_t cpu_mask = packet.GetU32(&offset); - s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); - } break; - - case KDP_READMEM: { - const uint32_t addr = packet.GetU32(&offset); - const uint32_t size = packet.GetU32(&offset); - s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); - m_last_read_memory_addr = addr; - } break; - - case KDP_WRITEMEM: { - const uint32_t addr = packet.GetU32(&offset); - const uint32_t size = packet.GetU32(&offset); - s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); - if (size > 0) - DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } break; - - case KDP_READMEM64: { - const uint64_t addr = packet.GetU64(&offset); - const uint32_t size = packet.GetU32(&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); - m_last_read_memory_addr = addr; - } break; - - case KDP_READPHYSMEM64: { - const uint64_t addr = packet.GetU64(&offset); - const uint32_t size = packet.GetU32(&offset); - const uint32_t lcpu = packet.GetU16(&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, - lcpu); - m_last_read_memory_addr = addr; - } break; - - case KDP_WRITEMEM64: { - const uint64_t addr = packet.GetU64(&offset); - const uint32_t size = packet.GetU32(&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, - size); - if (size > 0) - DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } break; - - case KDP_WRITEPHYSMEM64: { - const uint64_t addr = packet.GetU64(&offset); - const uint32_t size = packet.GetU32(&offset); - const uint32_t lcpu = packet.GetU16(&offset); - s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", - addr, size, lcpu); - if (size > 0) - DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); - } break; - - case KDP_READREGS: { - const uint32_t cpu = packet.GetU32(&offset); - const uint32_t flavor = packet.GetU32(&offset); - s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); - } break; - - case KDP_WRITEREGS: { - const uint32_t cpu = packet.GetU32(&offset); - const uint32_t flavor = packet.GetU32(&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); - if (nbytes > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within - // "packet" - eFormatHex, // Format to use - m_addr_byte_size, // Size of each item in - // bytes - nbytes / m_addr_byte_size, // Number of items - 16 / m_addr_byte_size, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses - // before each line - 0, 0); // No bitfields - } break; - - case KDP_BREAKPOINT_SET: - case KDP_BREAKPOINT_REMOVE: { - const uint32_t addr = packet.GetU32(&offset); - s.Printf(" (addr = 0x%8.8x)", addr); - } break; - - case KDP_BREAKPOINT_SET64: - case KDP_BREAKPOINT_REMOVE64: { - const uint64_t addr = packet.GetU64(&offset); - s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); - } break; - - case KDP_LOAD: { - const char *path = packet.GetCStr(&offset); - s.Printf(" (path = \"%s\")", path); - } break; - - case KDP_EXCEPTION: { - const uint32_t count = packet.GetU32(&offset); - - for (uint32_t i = 0; i < count; ++i) { - const uint32_t cpu = packet.GetU32(&offset); - const uint32_t exc = packet.GetU32(&offset); - const uint32_t code = packet.GetU32(&offset); - const uint32_t subcode = packet.GetU32(&offset); - const char *exc_cstr = NULL; - switch (exc) { - case 1: - exc_cstr = "EXC_BAD_ACCESS"; - break; - case 2: - exc_cstr = "EXC_BAD_INSTRUCTION"; - break; - case 3: - exc_cstr = "EXC_ARITHMETIC"; - break; - case 4: - exc_cstr = "EXC_EMULATION"; - break; - case 5: - exc_cstr = "EXC_SOFTWARE"; - break; - case 6: - exc_cstr = "EXC_BREAKPOINT"; - break; - case 7: - exc_cstr = "EXC_SYSCALL"; - break; - case 8: - exc_cstr = "EXC_MACH_SYSCALL"; - break; - case 9: - exc_cstr = "EXC_RPC_ALERT"; - break; - case 10: - exc_cstr = "EXC_CRASH"; - break; - default: - break; - } - - s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), " - "subcode = %u (0x%8.8x)} ", - cpu, exc_cstr, exc, code, code, subcode, subcode); - } - } break; - - case KDP_TERMINATION: { - const uint32_t term_code = packet.GetU32(&offset); - const uint32_t exit_code = packet.GetU32(&offset); - s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", - term_code, term_code, exit_code, exit_code); - } break; - - case KDP_REATTACH: { - const uint16_t reply_port = ntohs(packet.GetU16(&offset)); - s.Printf(" (reply_port = %u)", reply_port); - } break; - - case KDP_READMSR64: { - const uint32_t address = packet.GetU32(&offset); - const uint16_t lcpu = packet.GetU16(&offset); - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); - } break; - - case KDP_WRITEMSR64: { - const uint32_t address = packet.GetU32(&offset); - const uint16_t lcpu = packet.GetU16(&offset); - const uint32_t nbytes = packet.GetByteSize() - offset; - s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, - address, nbytes); - if (nbytes > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in - // bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses - // before each line - 0, 0); // No bitfields - } break; - - case KDP_READIOPORT: { - const uint16_t lcpu = packet.GetU16(&offset); - const uint16_t address = packet.GetU16(&offset); - const uint16_t nbytes = packet.GetU16(&offset); - s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, - nbytes); - } break; - - case KDP_WRITEIOPORT: { - const uint16_t lcpu = packet.GetU16(&offset); - const uint16_t address = packet.GetU16(&offset); - const uint16_t nbytes = packet.GetU16(&offset); - s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, - address, nbytes); - if (nbytes > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in - // bytes - nbytes, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses - // before each line - 0, 0); // No bitfields - } break; - - case KDP_DUMPINFO: { - const uint32_t count = packet.GetByteSize() - offset; - s.Printf(" (count = %u, bytes = \n", count); - if (count > 0) - DumpDataExtractor(packet, - &s, // Stream to dump to - offset, // Offset within "packet" - eFormatHex, // Format to use - 1, // Size of each item in bytes - count, // Number of items - 16, // Number per line - LLDB_INVALID_ADDRESS, // Don't show addresses before each line - 0, 0); // No bitfields - - } break; - } - } - } else { - error_desc = "error: invalid packet command: "; - } - } - - if (error_desc) { - s.PutCString(error_desc); - - DumpDataExtractor(packet, - &s, // Stream to dump to - 0, // Offset into "packet" - eFormatBytes, // Dump as hex bytes - 1, // Size of each item is 1 for - // single bytes - packet.GetByteSize(), // Number of bytes - UINT32_MAX, // Num bytes per line - LLDB_INVALID_ADDRESS, // Base address - 0, 0); // Bitfield info set to not do - // anything bitfield related - } -} - -uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu, - uint32_t flavor, void *dst, - uint32_t dst_len, - Status &error) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_READREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutHex32(cpu); - request_packet.PutHex32(flavor); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - uint32_t src_len = reply_packet.GetByteSize() - 12; - - if (src_len > 0) { - const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); - const void *src = reply_packet.GetData(&offset, bytes_to_copy); - if (src) { - ::memcpy(dst, src, bytes_to_copy); - error.Clear(); - // Return the number of bytes we could have returned regardless if we - // copied them or not, just so we know when things don't match up - return src_len; - } - } - if (kdp_error) - error.SetErrorStringWithFormat( - "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, - flavor, kdp_error); - else - error.SetErrorStringWithFormat( - "failed to read kdp registers for cpu %u flavor %u", cpu, flavor); - } else { - error.SetErrorString("failed to send packet"); - } - return 0; -} - -uint32_t CommunicationKDP::SendRequestWriteRegisters(uint32_t cpu, - uint32_t flavor, - const void *src, - uint32_t src_len, - Status &error) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_WRITEREGS; - // Size is header + 4 byte cpu and 4 byte flavor - const uint32_t command_length = 8 + 4 + 4 + src_len; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutHex32(cpu); - request_packet.PutHex32(flavor); - request_packet.Write(src, src_len); - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - if (kdp_error == 0) - return src_len; - error.SetErrorStringWithFormat( - "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, - flavor, kdp_error); - } else { - error.SetErrorString("failed to send packet"); - } - return 0; -} - -bool CommunicationKDP::SendRequestResume() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_RESUMECPUS; - const uint32_t command_length = 12; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutHex32(GetCPUMask()); - - DataExtractor reply_packet; - return SendRequestAndGetReply(command, request_packet, reply_packet); -} - -bool CommunicationKDP::SendRequestBreakpoint(bool set, addr_t addr) { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - bool use_64 = (GetVersion() >= 11); - uint32_t command_addr_byte_size = use_64 ? 8 : 4; - const CommandType command = - set ? (use_64 ? KDP_BREAKPOINT_SET64 : KDP_BREAKPOINT_SET) - : (use_64 ? KDP_BREAKPOINT_REMOVE64 : KDP_BREAKPOINT_REMOVE); - - const uint32_t command_length = 8 + command_addr_byte_size; - MakeRequestPacketHeader(command, request_packet, command_length); - request_packet.PutMaxHex64(addr, command_addr_byte_size); - - DataExtractor reply_packet; - if (SendRequestAndGetReply(command, request_packet, reply_packet)) { - lldb::offset_t offset = 8; - uint32_t kdp_error = reply_packet.GetU32(&offset); - if (kdp_error == 0) - return true; - } - return false; -} - -bool CommunicationKDP::SendRequestSuspend() { - PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, - m_byte_order); - const CommandType command = KDP_SUSPEND; - const uint32_t command_length = 8; - MakeRequestPacketHeader(command, request_packet, command_length); - DataExtractor reply_packet; - return SendRequestAndGetReply(command, request_packet, reply_packet); -} diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h deleted file mode 100644 index 64bfe55147350..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ /dev/null @@ -1,260 +0,0 @@ -//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_CommunicationKDP_h_ -#define liblldb_CommunicationKDP_h_ - -#include <list> -#include <mutex> -#include <string> - -#include "lldb/Core/Communication.h" -#include "lldb/Core/StreamBuffer.h" -#include "lldb/Utility/Listener.h" -#include "lldb/Utility/Predicate.h" -#include "lldb/lldb-private.h" - -class CommunicationKDP : public lldb_private::Communication { -public: - enum { eBroadcastBitRunPacketSent = kLoUserBroadcastBit }; - - const static uint32_t kMaxPacketSize = 1200; - const static uint32_t kMaxDataSize = 1024; - typedef lldb_private::StreamBuffer<1024> PacketStreamType; - typedef enum { - KDP_CONNECT = 0u, - KDP_DISCONNECT, - KDP_HOSTINFO, - KDP_VERSION, - KDP_MAXBYTES, - KDP_READMEM, - KDP_WRITEMEM, - KDP_READREGS, - KDP_WRITEREGS, - KDP_LOAD, - KDP_IMAGEPATH, - KDP_SUSPEND, - KDP_RESUMECPUS, - KDP_EXCEPTION, - KDP_TERMINATION, - KDP_BREAKPOINT_SET, - KDP_BREAKPOINT_REMOVE, - KDP_REGIONS, - KDP_REATTACH, - KDP_HOSTREBOOT, - KDP_READMEM64, - KDP_WRITEMEM64, - KDP_BREAKPOINT_SET64, - KDP_BREAKPOINT_REMOVE64, - KDP_KERNELVERSION, - KDP_READPHYSMEM64, - KDP_WRITEPHYSMEM64, - KDP_READIOPORT, - KDP_WRITEIOPORT, - KDP_READMSR64, - KDP_WRITEMSR64, - KDP_DUMPINFO - } CommandType; - - enum { KDP_FEATURE_BP = (1u << 0) }; - - typedef enum { - KDP_PROTERR_SUCCESS = 0, - KDP_PROTERR_ALREADY_CONNECTED, - KDP_PROTERR_BAD_NBYTES, - KDP_PROTERR_BADFLAVOR - } KDPError; - - typedef enum { - ePacketTypeRequest = 0x00u, - ePacketTypeReply = 0x80u, - ePacketTypeMask = 0x80u, - eCommandTypeMask = 0x7fu - } PacketType; - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - CommunicationKDP(const char *comm_name); - - virtual ~CommunicationKDP(); - - bool SendRequestPacket(const PacketStreamType &request_packet); - - // Wait for a packet within 'nsec' seconds - size_t - WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response, - uint32_t usec); - - bool GetSequenceMutex(std::unique_lock<std::recursive_mutex> &lock); - - bool CheckForPacket(const uint8_t *src, size_t src_len, - lldb_private::DataExtractor &packet); - bool IsRunning() const { return m_is_running.GetValue(); } - - //------------------------------------------------------------------ - // Set the global packet timeout. - // - // For clients, this is the timeout that gets used when sending - // packets and waiting for responses. For servers, this might not - // get used, and if it doesn't this should be moved to the - // CommunicationKDPClient. - //------------------------------------------------------------------ - std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) { - const auto old_packet_timeout = m_packet_timeout; - m_packet_timeout = packet_timeout; - return old_packet_timeout; - } - - std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; } - - //------------------------------------------------------------------ - // Public Request Packets - //------------------------------------------------------------------ - bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port, - const char *greeting); - - bool SendRequestReattach(uint16_t reply_port); - - bool SendRequestDisconnect(); - - uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst, - uint32_t dst_size, - lldb_private::Status &error); - - uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src, - uint32_t src_len, - lldb_private::Status &error); - - bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len, - lldb_private::DataExtractor &reply, - lldb_private::Status &error); - - uint32_t SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst, - uint32_t dst_size, - lldb_private::Status &error); - - uint32_t SendRequestWriteRegisters(uint32_t cpu, uint32_t flavor, - const void *src, uint32_t src_size, - lldb_private::Status &error); - - const char *GetKernelVersion(); - - // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... - // const char * - // GetImagePath (); - - uint32_t GetVersion(); - - uint32_t GetFeatureFlags(); - - bool LocalBreakpointsAreSupported() { - return (GetFeatureFlags() & KDP_FEATURE_BP) != 0; - } - - uint32_t GetCPUMask(); - - uint32_t GetCPUType(); - - uint32_t GetCPUSubtype(); - - lldb_private::UUID GetUUID(); - - bool RemoteIsEFI(); - - bool RemoteIsDarwinKernel(); - - lldb::addr_t GetLoadAddress(); - - bool SendRequestResume(); - - bool SendRequestSuspend(); - - bool SendRequestBreakpoint(bool set, lldb::addr_t addr); - -protected: - bool SendRequestPacketNoLock(const PacketStreamType &request_packet); - - size_t WaitForPacketWithTimeoutMicroSecondsNoLock( - lldb_private::DataExtractor &response, uint32_t timeout_usec); - - bool WaitForNotRunningPrivate(const std::chrono::microseconds &timeout); - - void MakeRequestPacketHeader(CommandType request_type, - PacketStreamType &request_packet, - uint16_t request_length); - - //------------------------------------------------------------------ - // Protected Request Packets (use public accessors which will cache - // results. - //------------------------------------------------------------------ - bool SendRequestVersion(); - - bool SendRequestHostInfo(); - - bool SendRequestKernelVersion(); - - // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection... - // bool - // SendRequestImagePath (); - - void DumpPacket(lldb_private::Stream &s, const void *data, uint32_t data_len); - - void DumpPacket(lldb_private::Stream &s, - const lldb_private::DataExtractor &extractor); - - bool VersionIsValid() const { return m_kdp_version_version != 0; } - - bool HostInfoIsValid() const { return m_kdp_hostinfo_cpu_type != 0; } - - bool ExtractIsReply(uint8_t first_packet_byte) const { - // TODO: handle big endian... - return (first_packet_byte & ePacketTypeMask) != 0; - } - - CommandType ExtractCommand(uint8_t first_packet_byte) const { - // TODO: handle big endian... - return (CommandType)(first_packet_byte & eCommandTypeMask); - } - - static const char *GetCommandAsCString(uint8_t command); - - void ClearKDPSettings(); - - bool SendRequestAndGetReply(const CommandType command, - const PacketStreamType &request_packet, - lldb_private::DataExtractor &reply_packet); - //------------------------------------------------------------------ - // Classes that inherit from CommunicationKDP can see and modify these - //------------------------------------------------------------------ - uint32_t m_addr_byte_size; - lldb::ByteOrder m_byte_order; - std::chrono::seconds m_packet_timeout; - std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving - // packets to a single thread at a time - lldb_private::Predicate<bool> m_is_running; - uint32_t m_session_key; - uint8_t m_request_sequence_id; - uint8_t m_exception_sequence_id; - uint32_t m_kdp_version_version; - uint32_t m_kdp_version_feature; - uint32_t m_kdp_hostinfo_cpu_mask; - uint32_t m_kdp_hostinfo_cpu_type; - uint32_t m_kdp_hostinfo_cpu_subtype; - std::string m_kernel_version; - // std::string m_image_path; // Disable KDP_IMAGEPATH for now, it seems to - // hang the KDP connection... - lldb::addr_t m_last_read_memory_addr; // Last memory read address for logging -private: - //------------------------------------------------------------------ - // For CommunicationKDP only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN(CommunicationKDP); -}; - -#endif // liblldb_CommunicationKDP_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp deleted file mode 100644 index c1c3678617c09..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ /dev/null @@ -1,1037 +0,0 @@ -//===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <errno.h> -#include <stdlib.h> - -#include <mutex> - -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/ConnectionFileDescriptor.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/Symbols.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/common/TCPSocket.h" -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandObject.h" -#include "lldb/Interpreter/CommandObjectMultiword.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionGroupString.h" -#include "lldb/Interpreter/OptionGroupUInt64.h" -#include "lldb/Interpreter/OptionValueProperties.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/StringExtractor.h" -#include "lldb/Utility/UUID.h" - -#include "llvm/Support/Threading.h" - -#define USEC_PER_SEC 1000000 - -#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" -#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h" -#include "ProcessKDP.h" -#include "ProcessKDPLog.h" -#include "ThreadKDP.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { - -static constexpr PropertyDefinition g_properties[] = { - {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {}, - "Specify the default packet timeout in seconds."}}; - -enum { ePropertyPacketTimeout }; - -class PluginProperties : public Properties { -public: - static ConstString GetSettingName() { - return ProcessKDP::GetPluginNameStatic(); - } - - PluginProperties() : Properties() { - m_collection_sp.reset(new OptionValueProperties(GetSettingName())); - m_collection_sp->Initialize(g_properties); - } - - virtual ~PluginProperties() {} - - uint64_t GetPacketTimeout() { - const uint32_t idx = ePropertyPacketTimeout; - return m_collection_sp->GetPropertyAtIndexAsUInt64( - NULL, idx, g_properties[idx].default_uint_value); - } -}; - -typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP; - -static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { - static ProcessKDPPropertiesSP g_settings_sp; - if (!g_settings_sp) - g_settings_sp.reset(new PluginProperties()); - return g_settings_sp; -} - -} // anonymous namespace end - -static const lldb::tid_t g_kernel_tid = 1; - -ConstString ProcessKDP::GetPluginNameStatic() { - static ConstString g_name("kdp-remote"); - return g_name; -} - -const char *ProcessKDP::GetPluginDescriptionStatic() { - return "KDP Remote protocol based debugging plug-in for darwin kernel " - "debugging."; -} - -void ProcessKDP::Terminate() { - PluginManager::UnregisterPlugin(ProcessKDP::CreateInstance); -} - -lldb::ProcessSP ProcessKDP::CreateInstance(TargetSP target_sp, - ListenerSP listener_sp, - const FileSpec *crash_file_path) { - lldb::ProcessSP process_sp; - if (crash_file_path == NULL) - process_sp.reset(new ProcessKDP(target_sp, listener_sp)); - return process_sp; -} - -bool ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) { - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - Module *exe_module = target_sp->GetExecutableModulePointer(); - if (exe_module) { - const llvm::Triple &triple_ref = target_sp->GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: // Should use "macosx" for desktop and "ios" for - // iOS, but accept darwin just in case - case llvm::Triple::MacOSX: // For desktop targets - case llvm::Triple::IOS: // For arm targets - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - if (triple_ref.getVendor() == llvm::Triple::Apple) { - ObjectFile *exe_objfile = exe_module->GetObjectFile(); - if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && - exe_objfile->GetStrata() == ObjectFile::eStrataKernel) - return true; - } - break; - - default: - break; - } - } - return false; -} - -//---------------------------------------------------------------------- -// ProcessKDP constructor -//---------------------------------------------------------------------- -ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) - : Process(target_sp, listener_sp), - m_comm("lldb.process.kdp-remote.communication"), - m_async_broadcaster(NULL, "lldb.process.kdp-remote.async-broadcaster"), - m_dyld_plugin_name(), m_kernel_load_addr(LLDB_INVALID_ADDRESS), - m_command_sp(), m_kernel_thread_wp() { - m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, - "async thread should exit"); - m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, - "async thread continue"); - const uint64_t timeout_seconds = - GetGlobalPluginProperties()->GetPacketTimeout(); - if (timeout_seconds > 0) - m_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds)); -} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ProcessKDP::~ProcessKDP() { - Clear(); - // We need to call finalize on the process before destroying ourselves to - // make sure all of the broadcaster cleanup goes as planned. If we destruct - // this class, then Process::~Process() might have problems trying to fully - // destroy the broadcaster. - Finalize(); -} - -//---------------------------------------------------------------------- -// PluginInterface -//---------------------------------------------------------------------- -lldb_private::ConstString ProcessKDP::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ProcessKDP::GetPluginVersion() { return 1; } - -Status ProcessKDP::WillLaunch(Module *module) { - Status error; - error.SetErrorString("launching not supported in kdp-remote plug-in"); - return error; -} - -Status ProcessKDP::WillAttachToProcessWithID(lldb::pid_t pid) { - Status error; - error.SetErrorString( - "attaching to a by process ID not supported in kdp-remote plug-in"); - return error; -} - -Status ProcessKDP::WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) { - Status error; - error.SetErrorString( - "attaching to a by process name not supported in kdp-remote plug-in"); - return error; -} - -bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { - uint32_t cpu = m_comm.GetCPUType(); - if (cpu) { - uint32_t sub = m_comm.GetCPUSubtype(); - arch.SetArchitecture(eArchTypeMachO, cpu, sub); - // Leave architecture vendor as unspecified unknown - arch.GetTriple().setVendor(llvm::Triple::UnknownVendor); - arch.GetTriple().setVendorName(llvm::StringRef()); - return true; - } - arch.Clear(); - return false; -} - -Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { - Status error; - - // Don't let any JIT happen when doing KDP as we can't allocate memory and we - // don't want to be mucking with threads that might already be handling - // exceptions - SetCanJIT(false); - - if (remote_url.empty()) { - error.SetErrorStringWithFormat("empty connection URL"); - return error; - } - - std::unique_ptr<ConnectionFileDescriptor> conn_ap( - new ConnectionFileDescriptor()); - if (conn_ap.get()) { - // Only try once for now. - // TODO: check if we should be retrying? - const uint32_t max_retry_count = 1; - for (uint32_t retry_count = 0; retry_count < max_retry_count; - ++retry_count) { - if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) - break; - usleep(100000); - } - } - - if (conn_ap->IsConnected()) { - const TCPSocket &socket = - static_cast<const TCPSocket &>(*conn_ap->GetReadObject()); - const uint16_t reply_port = socket.GetLocalPortNumber(); - - if (reply_port != 0) { - m_comm.SetConnection(conn_ap.release()); - - if (m_comm.SendRequestReattach(reply_port)) { - if (m_comm.SendRequestConnect(reply_port, reply_port, - "Greetings from LLDB...")) { - m_comm.GetVersion(); - - Target &target = GetTarget(); - ArchSpec kernel_arch; - // The host architecture - GetHostArchitecture(kernel_arch); - ArchSpec target_arch = target.GetArchitecture(); - // Merge in any unspecified stuff into the target architecture in - // case the target arch isn't set at all or incompletely. - target_arch.MergeFrom(kernel_arch); - target.SetArchitecture(target_arch); - - /* Get the kernel's UUID and load address via KDP_KERNELVERSION - * packet. */ - /* An EFI kdp session has neither UUID nor load address. */ - - UUID kernel_uuid = m_comm.GetUUID(); - addr_t kernel_load_addr = m_comm.GetLoadAddress(); - - if (m_comm.RemoteIsEFI()) { - // Select an invalid plugin name for the dynamic loader so one - // doesn't get used since EFI does its own manual loading via - // python scripting - static ConstString g_none_dynamic_loader("none"); - m_dyld_plugin_name = g_none_dynamic_loader; - - if (kernel_uuid.IsValid()) { - // If EFI passed in a UUID= try to lookup UUID The slide will not - // be provided. But the UUID lookup will be used to launch EFI - // debug scripts from the dSYM, that can load all of the symbols. - ModuleSpec module_spec; - module_spec.GetUUID() = kernel_uuid; - module_spec.GetArchitecture() = target.GetArchitecture(); - - // Lookup UUID locally, before attempting dsymForUUID like action - module_spec.GetSymbolFileSpec() = - Symbols::LocateExecutableSymbolFile(module_spec); - if (module_spec.GetSymbolFileSpec()) { - ModuleSpec executable_module_spec = - Symbols::LocateExecutableObjectFile(module_spec); - if (FileSystem::Instance().Exists( - executable_module_spec.GetFileSpec())) { - module_spec.GetFileSpec() = - executable_module_spec.GetFileSpec(); - } - } - if (!module_spec.GetSymbolFileSpec() || - !module_spec.GetSymbolFileSpec()) - Symbols::DownloadObjectAndSymbolFile(module_spec, true); - - if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { - ModuleSP module_sp(new Module(module_spec)); - if (module_sp.get() && module_sp->GetObjectFile()) { - // Get the current target executable - ModuleSP exe_module_sp(target.GetExecutableModule()); - - // Make sure you don't already have the right module loaded - // and they will be uniqued - if (exe_module_sp.get() != module_sp.get()) - target.SetExecutableModule(module_sp, eLoadDependentsNo); - } - } - } - } else if (m_comm.RemoteIsDarwinKernel()) { - m_dyld_plugin_name = - DynamicLoaderDarwinKernel::GetPluginNameStatic(); - if (kernel_load_addr != LLDB_INVALID_ADDRESS) { - m_kernel_load_addr = kernel_load_addr; - } - } - - // Set the thread ID - UpdateThreadListIfNeeded(); - SetID(1); - GetThreadList(); - SetPrivateState(eStateStopped); - StreamSP async_strm_sp(target.GetDebugger().GetAsyncOutputStream()); - if (async_strm_sp) { - const char *cstr; - if ((cstr = m_comm.GetKernelVersion()) != NULL) { - async_strm_sp->Printf("Version: %s\n", cstr); - async_strm_sp->Flush(); - } - // if ((cstr = m_comm.GetImagePath ()) != NULL) - // { - // async_strm_sp->Printf ("Image Path: - // %s\n", cstr); - // async_strm_sp->Flush(); - // } - } - } else { - error.SetErrorString("KDP_REATTACH failed"); - } - } else { - error.SetErrorString("KDP_REATTACH failed"); - } - } else { - error.SetErrorString("invalid reply port from UDP connection"); - } - } else { - if (error.Success()) - error.SetErrorStringWithFormat("failed to connect to '%s'", - remote_url.str().c_str()); - } - if (error.Fail()) - m_comm.Disconnect(); - - return error; -} - -//---------------------------------------------------------------------- -// Process Control -//---------------------------------------------------------------------- -Status ProcessKDP::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) { - Status error; - error.SetErrorString("launching not supported in kdp-remote plug-in"); - return error; -} - -Status -ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid, - const ProcessAttachInfo &attach_info) { - Status error; - error.SetErrorString( - "attach to process by ID is not supported in kdp remote debugging"); - return error; -} - -Status -ProcessKDP::DoAttachToProcessWithName(const char *process_name, - const ProcessAttachInfo &attach_info) { - Status error; - error.SetErrorString( - "attach to process by name is not supported in kdp remote debugging"); - return error; -} - -void ProcessKDP::DidAttach(ArchSpec &process_arch) { - Process::DidAttach(process_arch); - - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - if (log) - log->Printf("ProcessKDP::DidAttach()"); - if (GetID() != LLDB_INVALID_PROCESS_ID) { - GetHostArchitecture(process_arch); - } -} - -addr_t ProcessKDP::GetImageInfoAddress() { return m_kernel_load_addr; } - -lldb_private::DynamicLoader *ProcessKDP::GetDynamicLoader() { - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset(DynamicLoader::FindPlugin( - this, - m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); - return m_dyld_ap.get(); -} - -Status ProcessKDP::WillResume() { return Status(); } - -Status ProcessKDP::DoResume() { - Status error; - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - // Only start the async thread if we try to do any process control - if (!m_async_thread.IsJoinable()) - StartAsyncThread(); - - bool resume = false; - - // With KDP there is only one thread we can tell what to do - ThreadSP kernel_thread_sp(m_thread_list.FindThreadByProtocolID(g_kernel_tid)); - - if (kernel_thread_sp) { - const StateType thread_resume_state = - kernel_thread_sp->GetTemporaryResumeState(); - - if (log) - log->Printf("ProcessKDP::DoResume() thread_resume_state = %s", - StateAsCString(thread_resume_state)); - switch (thread_resume_state) { - case eStateSuspended: - // Nothing to do here when a thread will stay suspended we just leave the - // CPU mask bit set to zero for the thread - if (log) - log->Printf("ProcessKDP::DoResume() = suspended???"); - break; - - case eStateStepping: { - lldb::RegisterContextSP reg_ctx_sp( - kernel_thread_sp->GetRegisterContext()); - - if (reg_ctx_sp) { - if (log) - log->Printf( - "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);"); - reg_ctx_sp->HardwareSingleStep(true); - resume = true; - } else { - error.SetErrorStringWithFormat( - "KDP thread 0x%llx has no register context", - kernel_thread_sp->GetID()); - } - } break; - - case eStateRunning: { - lldb::RegisterContextSP reg_ctx_sp( - kernel_thread_sp->GetRegisterContext()); - - if (reg_ctx_sp) { - if (log) - log->Printf("ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep " - "(false);"); - reg_ctx_sp->HardwareSingleStep(false); - resume = true; - } else { - error.SetErrorStringWithFormat( - "KDP thread 0x%llx has no register context", - kernel_thread_sp->GetID()); - } - } break; - - default: - // The only valid thread resume states are listed above - llvm_unreachable("invalid thread resume state"); - } - } - - if (resume) { - if (log) - log->Printf("ProcessKDP::DoResume () sending resume"); - - if (m_comm.SendRequestResume()) { - m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); - SetPrivateState(eStateRunning); - } else - error.SetErrorString("KDP resume failed"); - } else { - error.SetErrorString("kernel thread is suspended"); - } - - return error; -} - -lldb::ThreadSP ProcessKDP::GetKernelThread() { - // KDP only tells us about one thread/core. Any other threads will usually - // be the ones that are read from memory by the OS plug-ins. - - ThreadSP thread_sp(m_kernel_thread_wp.lock()); - if (!thread_sp) { - thread_sp.reset(new ThreadKDP(*this, g_kernel_tid)); - m_kernel_thread_wp = thread_sp; - } - return thread_sp; -} - -bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) { - // locker will keep a mutex locked until it goes out of scope - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD)); - LLDB_LOGV(log, "pid = {0}", GetID()); - - // Even though there is a CPU mask, it doesn't mean we can see each CPU - // individually, there is really only one. Lets call this thread 1. - ThreadSP thread_sp( - old_thread_list.FindThreadByProtocolID(g_kernel_tid, false)); - if (!thread_sp) - thread_sp = GetKernelThread(); - new_thread_list.AddThread(thread_sp); - - return new_thread_list.GetSize(false) > 0; -} - -void ProcessKDP::RefreshStateAfterStop() { - // Let all threads recover from stopping and do any clean up based on the - // previous thread state (if any). - m_thread_list.RefreshStateAfterStop(); -} - -Status ProcessKDP::DoHalt(bool &caused_stop) { - Status error; - - if (m_comm.IsRunning()) { - if (m_destroy_in_process) { - // If we are attempting to destroy, we need to not return an error to Halt - // or DoDestroy won't get called. We are also currently running, so send - // a process stopped event - SetPrivateState(eStateStopped); - } else { - error.SetErrorString("KDP cannot interrupt a running kernel"); - } - } - return error; -} - -Status ProcessKDP::DoDetach(bool keep_stopped) { - Status error; - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - if (log) - log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped); - - if (m_comm.IsRunning()) { - // We are running and we can't interrupt a running kernel, so we need to - // just close the connection to the kernel and hope for the best - } else { - // If we are going to keep the target stopped, then don't send the - // disconnect message. - if (!keep_stopped && m_comm.IsConnected()) { - const bool success = m_comm.SendRequestDisconnect(); - if (log) { - if (success) - log->PutCString( - "ProcessKDP::DoDetach() detach packet sent successfully"); - else - log->PutCString( - "ProcessKDP::DoDetach() connection channel shutdown failed"); - } - m_comm.Disconnect(); - } - } - StopAsyncThread(); - m_comm.Clear(); - - SetPrivateState(eStateDetached); - ResumePrivateStateThread(); - - // KillDebugserverProcess (); - return error; -} - -Status ProcessKDP::DoDestroy() { - // For KDP there really is no difference between destroy and detach - bool keep_stopped = false; - return DoDetach(keep_stopped); -} - -//------------------------------------------------------------------ -// Process Queries -//------------------------------------------------------------------ - -bool ProcessKDP::IsAlive() { - return m_comm.IsConnected() && Process::IsAlive(); -} - -//------------------------------------------------------------------ -// Process Memory -//------------------------------------------------------------------ -size_t ProcessKDP::DoReadMemory(addr_t addr, void *buf, size_t size, - Status &error) { - uint8_t *data_buffer = (uint8_t *)buf; - if (m_comm.IsConnected()) { - const size_t max_read_size = 512; - size_t total_bytes_read = 0; - - // Read the requested amount of memory in 512 byte chunks - while (total_bytes_read < size) { - size_t bytes_to_read_this_request = size - total_bytes_read; - if (bytes_to_read_this_request > max_read_size) { - bytes_to_read_this_request = max_read_size; - } - size_t bytes_read = m_comm.SendRequestReadMemory( - addr + total_bytes_read, data_buffer + total_bytes_read, - bytes_to_read_this_request, error); - total_bytes_read += bytes_read; - if (error.Fail() || bytes_read == 0) { - return total_bytes_read; - } - } - - return total_bytes_read; - } - error.SetErrorString("not connected"); - return 0; -} - -size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size, - Status &error) { - if (m_comm.IsConnected()) - return m_comm.SendRequestWriteMemory(addr, buf, size, error); - error.SetErrorString("not connected"); - return 0; -} - -lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) { - error.SetErrorString( - "memory allocation not supported in kdp remote debugging"); - return LLDB_INVALID_ADDRESS; -} - -Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) { - Status error; - error.SetErrorString( - "memory deallocation not supported in kdp remote debugging"); - return error; -} - -Status ProcessKDP::EnableBreakpointSite(BreakpointSite *bp_site) { - if (m_comm.LocalBreakpointsAreSupported()) { - Status error; - if (!bp_site->IsEnabled()) { - if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress())) { - bp_site->SetEnabled(true); - bp_site->SetType(BreakpointSite::eExternal); - } else { - error.SetErrorString("KDP set breakpoint failed"); - } - } - return error; - } - return EnableSoftwareBreakpoint(bp_site); -} - -Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) { - if (m_comm.LocalBreakpointsAreSupported()) { - Status error; - if (bp_site->IsEnabled()) { - BreakpointSite::Type bp_type = bp_site->GetType(); - if (bp_type == BreakpointSite::eExternal) { - if (m_destroy_in_process && m_comm.IsRunning()) { - // We are trying to destroy our connection and we are running - bp_site->SetEnabled(false); - } else { - if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress())) - bp_site->SetEnabled(false); - else - error.SetErrorString("KDP remove breakpoint failed"); - } - } else { - error = DisableSoftwareBreakpoint(bp_site); - } - } - return error; - } - return DisableSoftwareBreakpoint(bp_site); -} - -Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) { - Status error; - error.SetErrorString( - "watchpoints are not supported in kdp remote debugging"); - return error; -} - -Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) { - Status error; - error.SetErrorString( - "watchpoints are not supported in kdp remote debugging"); - return error; -} - -void ProcessKDP::Clear() { m_thread_list.Clear(); } - -Status ProcessKDP::DoSignal(int signo) { - Status error; - error.SetErrorString( - "sending signals is not supported in kdp remote debugging"); - return error; -} - -void ProcessKDP::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - DebuggerInitialize); - - ProcessKDPLog::Initialize(); - }); -} - -void ProcessKDP::DebuggerInitialize(lldb_private::Debugger &debugger) { - if (!PluginManager::GetSettingForProcessPlugin( - debugger, PluginProperties::GetSettingName())) { - const bool is_global_setting = true; - PluginManager::CreateSettingForProcessPlugin( - debugger, GetGlobalPluginProperties()->GetValueProperties(), - ConstString("Properties for the kdp-remote process plug-in."), - is_global_setting); - } -} - -bool ProcessKDP::StartAsyncThread() { - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - - if (log) - log->Printf("ProcessKDP::StartAsyncThread ()"); - - if (m_async_thread.IsJoinable()) - return true; - - m_async_thread = ThreadLauncher::LaunchThread( - "<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL); - return m_async_thread.IsJoinable(); -} - -void ProcessKDP::StopAsyncThread() { - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - - if (log) - log->Printf("ProcessKDP::StopAsyncThread ()"); - - m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit); - - // Stop the stdio thread - if (m_async_thread.IsJoinable()) - m_async_thread.Join(nullptr); -} - -void *ProcessKDP::AsyncThread(void *arg) { - ProcessKDP *process = (ProcessKDP *)arg; - - const lldb::pid_t pid = process->GetID(); - - Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); - if (log) - log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 - ") thread starting...", - arg, pid); - - ListenerSP listener_sp(Listener::MakeListener("ProcessKDP::AsyncThread")); - EventSP event_sp; - const uint32_t desired_event_mask = - eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; - - if (listener_sp->StartListeningForEvents(&process->m_async_broadcaster, - desired_event_mask) == - desired_event_mask) { - bool done = false; - while (!done) { - if (log) - log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp)...", - pid); - if (listener_sp->GetEvent(event_sp, llvm::None)) { - uint32_t event_type = event_sp->GetType(); - if (log) - log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 - ") Got an event of type: %d...", - pid, event_type); - - // When we are running, poll for 1 second to try and get an exception - // to indicate the process has stopped. If we don't get one, check to - // make sure no one asked us to exit - bool is_running = false; - DataExtractor exc_reply_packet; - do { - switch (event_type) { - case eBroadcastBitAsyncContinue: { - is_running = true; - if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds( - exc_reply_packet, 1 * USEC_PER_SEC)) { - ThreadSP thread_sp(process->GetKernelThread()); - if (thread_sp) { - lldb::RegisterContextSP reg_ctx_sp( - thread_sp->GetRegisterContext()); - if (reg_ctx_sp) - reg_ctx_sp->InvalidateAllRegisters(); - static_cast<ThreadKDP *>(thread_sp.get()) - ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet); - } - - // TODO: parse the stop reply packet - is_running = false; - process->SetPrivateState(eStateStopped); - } else { - // Check to see if we are supposed to exit. There is no way to - // interrupt a running kernel, so all we can do is wait for an - // exception or detach... - if (listener_sp->GetEvent(event_sp, - std::chrono::microseconds(0))) { - // We got an event, go through the loop again - event_type = event_sp->GetType(); - } - } - } break; - - case eBroadcastBitAsyncThreadShouldExit: - if (log) - log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 - ") got eBroadcastBitAsyncThreadShouldExit...", - pid); - done = true; - is_running = false; - break; - - default: - if (log) - log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 - ") got unknown event 0x%8.8x", - pid, event_type); - done = true; - is_running = false; - break; - } - } while (is_running); - } else { - if (log) - log->Printf("ProcessKDP::AsyncThread (pid = %" PRIu64 - ") listener.WaitForEvent (NULL, event_sp) => false", - pid); - done = true; - } - } - } - - if (log) - log->Printf("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 - ") thread exiting...", - arg, pid); - - process->m_async_thread.Reset(); - return NULL; -} - -class CommandObjectProcessKDPPacketSend : public CommandObjectParsed { -private: - OptionGroupOptions m_option_group; - OptionGroupUInt64 m_command_byte; - OptionGroupString m_packet_data; - - virtual Options *GetOptions() { return &m_option_group; } - -public: - CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "process plugin packet send", - "Send a custom packet through the KDP protocol by " - "specifying the command byte and the packet " - "payload data. A packet will be sent with a " - "correct header and payload, and the raw result " - "bytes will be displayed as a string value. ", - NULL), - m_option_group(), - m_command_byte(LLDB_OPT_SET_1, true, "command", 'c', 0, eArgTypeNone, - "Specify the command byte to use when sending the KDP " - "request packet.", - 0), - m_packet_data(LLDB_OPT_SET_1, false, "payload", 'p', 0, eArgTypeNone, - "Specify packet payload bytes as a hex ASCII string with " - "no spaces or hex prefixes.", - NULL) { - m_option_group.Append(&m_command_byte, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append(&m_packet_data, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Finalize(); - } - - ~CommandObjectProcessKDPPacketSend() {} - - bool DoExecute(Args &command, CommandReturnObject &result) { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) { - if (!m_command_byte.GetOptionValue().OptionWasSet()) { - result.AppendError( - "the --command option must be set to a valid command byte"); - result.SetStatus(eReturnStatusFailed); - } else { - const uint64_t command_byte = - m_command_byte.GetOptionValue().GetUInt64Value(0); - if (command_byte > 0 && command_byte <= UINT8_MAX) { - ProcessKDP *process = - (ProcessKDP *)m_interpreter.GetExecutionContext().GetProcessPtr(); - if (process) { - const StateType state = process->GetState(); - - if (StateIsStoppedState(state, true)) { - std::vector<uint8_t> payload_bytes; - const char *ascii_hex_bytes_cstr = - m_packet_data.GetOptionValue().GetCurrentValue(); - if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) { - StringExtractor extractor(ascii_hex_bytes_cstr); - const size_t ascii_hex_bytes_cstr_len = - extractor.GetStringRef().size(); - if (ascii_hex_bytes_cstr_len & 1) { - result.AppendErrorWithFormat("payload data must contain an " - "even number of ASCII hex " - "characters: '%s'", - ascii_hex_bytes_cstr); - result.SetStatus(eReturnStatusFailed); - return false; - } - payload_bytes.resize(ascii_hex_bytes_cstr_len / 2); - if (extractor.GetHexBytes(payload_bytes, '\xdd') != - payload_bytes.size()) { - result.AppendErrorWithFormat("payload data must only contain " - "ASCII hex characters (no " - "spaces or hex prefixes): '%s'", - ascii_hex_bytes_cstr); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - Status error; - DataExtractor reply; - process->GetCommunication().SendRawRequest( - command_byte, - payload_bytes.empty() ? NULL : payload_bytes.data(), - payload_bytes.size(), reply, error); - - if (error.Success()) { - // Copy the binary bytes into a hex ASCII string for the result - StreamString packet; - packet.PutBytesAsRawHex8( - reply.GetDataStart(), reply.GetByteSize(), - endian::InlHostByteOrder(), endian::InlHostByteOrder()); - result.AppendMessage(packet.GetString()); - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } else { - const char *error_cstr = error.AsCString(); - if (error_cstr && error_cstr[0]) - result.AppendError(error_cstr); - else - result.AppendErrorWithFormat("unknown error 0x%8.8x", - error.GetError()); - result.SetStatus(eReturnStatusFailed); - return false; - } - } else { - result.AppendErrorWithFormat("process must be stopped in order " - "to send KDP packets, state is %s", - StateAsCString(state)); - result.SetStatus(eReturnStatusFailed); - } - } else { - result.AppendError("invalid process"); - result.SetStatus(eReturnStatusFailed); - } - } else { - result.AppendErrorWithFormat("invalid command byte 0x%" PRIx64 - ", valid values are 1 - 255", - command_byte); - result.SetStatus(eReturnStatusFailed); - } - } - } else { - result.AppendErrorWithFormat("'%s' takes no arguments, only options.", - m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - } - return false; - } -}; - -class CommandObjectProcessKDPPacket : public CommandObjectMultiword { -private: -public: - CommandObjectProcessKDPPacket(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "process plugin packet", - "Commands that deal with KDP remote packets.", - NULL) { - LoadSubCommand( - "send", - CommandObjectSP(new CommandObjectProcessKDPPacketSend(interpreter))); - } - - ~CommandObjectProcessKDPPacket() {} -}; - -class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { -public: - CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "process plugin", - "Commands for operating on a ProcessKDP process.", - "process plugin <subcommand> [<subcommand-options>]") { - LoadSubCommand("packet", CommandObjectSP(new CommandObjectProcessKDPPacket( - interpreter))); - } - - ~CommandObjectMultiwordProcessKDP() {} -}; - -CommandObject *ProcessKDP::GetPluginCommandObject() { - if (!m_command_sp) - m_command_sp.reset(new CommandObjectMultiwordProcessKDP( - GetTarget().GetDebugger().GetCommandInterpreter())); - return m_command_sp.get(); -} diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h deleted file mode 100644 index f9102442de935..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ /dev/null @@ -1,220 +0,0 @@ -//===-- ProcessKDP.h --------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessKDP_h_ -#define liblldb_ProcessKDP_h_ - - -#include <list> -#include <vector> - -#include "lldb/Core/ThreadSafeValue.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/Broadcaster.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Status.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/StringList.h" - -#include "CommunicationKDP.h" - -class ThreadKDP; - -class ProcessKDP : public lldb_private::Process { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, - const lldb_private::FileSpec *crash_file_path); - - static void Initialize(); - - static void DebuggerInitialize(lldb_private::Debugger &debugger); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ProcessKDP(lldb::TargetSP target_sp, lldb::ListenerSP listener); - - ~ProcessKDP() override; - - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - bool CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) override; - lldb_private::CommandObject *GetPluginCommandObject() override; - - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - lldb_private::Status WillLaunch(lldb_private::Module *module) override; - - lldb_private::Status - DoLaunch(lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info) override; - - lldb_private::Status WillAttachToProcessWithID(lldb::pid_t pid) override; - - lldb_private::Status - WillAttachToProcessWithName(const char *process_name, - bool wait_for_launch) override; - - lldb_private::Status DoConnectRemote(lldb_private::Stream *strm, - llvm::StringRef remote_url) override; - - lldb_private::Status DoAttachToProcessWithID( - lldb::pid_t pid, - const lldb_private::ProcessAttachInfo &attach_info) override; - - lldb_private::Status DoAttachToProcessWithName( - const char *process_name, - const lldb_private::ProcessAttachInfo &attach_info) override; - - void DidAttach(lldb_private::ArchSpec &process_arch) override; - - lldb::addr_t GetImageInfoAddress() override; - - lldb_private::DynamicLoader *GetDynamicLoader() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - lldb_private::Status WillResume() override; - - lldb_private::Status DoResume() override; - - lldb_private::Status DoHalt(bool &caused_stop) override; - - lldb_private::Status DoDetach(bool keep_stopped) override; - - lldb_private::Status DoSignal(int signal) override; - - lldb_private::Status DoDestroy() override; - - void RefreshStateAfterStop() override; - - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - bool IsAlive() override; - - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, - lldb_private::Status &error) override; - - size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, - lldb_private::Status &error) override; - - lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Status &error) override; - - lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override; - - //---------------------------------------------------------------------- - // Process Breakpoints - //---------------------------------------------------------------------- - lldb_private::Status - EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - lldb_private::Status - DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - - //---------------------------------------------------------------------- - // Process Watchpoints - //---------------------------------------------------------------------- - lldb_private::Status EnableWatchpoint(lldb_private::Watchpoint *wp, - bool notify = true) override; - - lldb_private::Status DisableWatchpoint(lldb_private::Watchpoint *wp, - bool notify = true) override; - - CommunicationKDP &GetCommunication() { return m_comm; } - -protected: - friend class ThreadKDP; - friend class CommunicationKDP; - - //---------------------------------------------------------------------- - // Accessors - //---------------------------------------------------------------------- - bool IsRunning(lldb::StateType state) { - return state == lldb::eStateRunning || IsStepping(state); - } - - bool IsStepping(lldb::StateType state) { - return state == lldb::eStateStepping; - } - - bool CanResume(lldb::StateType state) { return state == lldb::eStateStopped; } - - bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; } - - bool GetHostArchitecture(lldb_private::ArchSpec &arch); - - bool ProcessIDIsValid() const; - - void Clear(); - - bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; - - enum { - eBroadcastBitAsyncContinue = (1 << 0), - eBroadcastBitAsyncThreadShouldExit = (1 << 1) - }; - - lldb::ThreadSP GetKernelThread(); - - //------------------------------------------------------------------ - /// Broadcaster event bits definitions. - //------------------------------------------------------------------ - CommunicationKDP m_comm; - lldb_private::Broadcaster m_async_broadcaster; - lldb_private::HostThread m_async_thread; - lldb_private::ConstString m_dyld_plugin_name; - lldb::addr_t m_kernel_load_addr; - lldb::CommandObjectSP m_command_sp; - lldb::ThreadWP m_kernel_thread_wp; - - bool StartAsyncThread(); - - void StopAsyncThread(); - - static void *AsyncThread(void *arg); - -private: - //------------------------------------------------------------------ - // For ProcessKDP only - //------------------------------------------------------------------ - - DISALLOW_COPY_AND_ASSIGN(ProcessKDP); -}; - -#endif // liblldb_ProcessKDP_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp deleted file mode 100644 index ffab3e5e23c77..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===-- ProcessKDPLog.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessKDPLog.h" - -using namespace lldb_private; - -static constexpr Log::Category g_categories[] = { - {{"async"}, {"log asynchronous activity"}, KDP_LOG_ASYNC}, - {{"break"}, {"log breakpoints"}, KDP_LOG_BREAKPOINTS}, - {{"comm"}, {"log communication activity"}, KDP_LOG_COMM}, - {{"data-long"}, - {"log memory bytes for memory reads and writes for all transactions"}, - KDP_LOG_MEMORY_DATA_LONG}, - {{"data-short"}, - {"log memory bytes for memory reads and writes for short transactions " - "only"}, - KDP_LOG_MEMORY_DATA_SHORT}, - {{"memory"}, {"log memory reads and writes"}, KDP_LOG_MEMORY}, - {{"packets"}, {"log gdb remote packets"}, KDP_LOG_PACKETS}, - {{"process"}, {"log process events and activities"}, KDP_LOG_PROCESS}, - {{"step"}, {"log step related activities"}, KDP_LOG_STEP}, - {{"thread"}, {"log thread events and activities"}, KDP_LOG_THREAD}, - {{"watch"}, {"log watchpoint related activities"}, KDP_LOG_WATCHPOINTS}, -}; - -Log::Channel ProcessKDPLog::g_channel(g_categories, KDP_LOG_DEFAULT); - -void ProcessKDPLog::Initialize() { Log::Register("kdp-remote", g_channel); } diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h deleted file mode 100644 index 908754ec992b1..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- ProcessKDPLog.h -----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessKDPLog_h_ -#define liblldb_ProcessKDPLog_h_ - -#include "lldb/Utility/Log.h" - -#define KDP_LOG_PROCESS (1u << 1) -#define KDP_LOG_THREAD (1u << 2) -#define KDP_LOG_PACKETS (1u << 3) -#define KDP_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define KDP_LOG_MEMORY_DATA_SHORT \ - (1u << 5) // Log short memory reads/writes bytes -#define KDP_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define KDP_LOG_BREAKPOINTS (1u << 7) -#define KDP_LOG_WATCHPOINTS (1u << 8) -#define KDP_LOG_STEP (1u << 9) -#define KDP_LOG_COMM (1u << 10) -#define KDP_LOG_ASYNC (1u << 11) -#define KDP_LOG_ALL (UINT32_MAX) -#define KDP_LOG_DEFAULT KDP_LOG_PACKETS - -namespace lldb_private { -class ProcessKDPLog { - static Log::Channel g_channel; - -public: - static void Initialize(); - - static Log *GetLogIfAllCategoriesSet(uint32_t mask) { - return g_channel.GetLogIfAll(mask); - } -}; -} - -#endif // liblldb_ProcessKDPLog_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp deleted file mode 100644 index 0f9e62ce355a0..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//===-- RegisterContextKDP_arm.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "RegisterContextKDP_arm.h" - -#include "ProcessKDP.h" -#include "ThreadKDP.h" - -using namespace lldb; -using namespace lldb_private; - -RegisterContextKDP_arm::RegisterContextKDP_arm(ThreadKDP &thread, - uint32_t concrete_frame_idx) - : RegisterContextDarwin_arm(thread, concrete_frame_idx), - m_kdp_thread(thread) {} - -RegisterContextKDP_arm::~RegisterContextKDP_arm() {} - -int RegisterContextKDP_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoWriteGPR(lldb::tid_t tid, int flavor, - const GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoWriteFPU(lldb::tid_t tid, int flavor, - const FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoWriteEXC(lldb::tid_t tid, int flavor, - const EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm::DoWriteDBG(lldb::tid_t tid, int flavor, - const DBG &dbg) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h deleted file mode 100644 index 1532f23207f42..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h +++ /dev/null @@ -1,44 +0,0 @@ -//===-- RegisterContextKDP_arm.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextKDP_arm_h_ -#define liblldb_RegisterContextKDP_arm_h_ - - -#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h" - -class ThreadKDP; - -class RegisterContextKDP_arm : public RegisterContextDarwin_arm { -public: - RegisterContextKDP_arm(ThreadKDP &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextKDP_arm(); - -protected: - virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); - - int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg); - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); - - int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); - - ThreadKDP &m_kdp_thread; -}; - -#endif // liblldb_RegisterContextKDP_arm_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp deleted file mode 100644 index e13a7f3ad9079..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp +++ /dev/null @@ -1,148 +0,0 @@ -//===-- RegisterContextKDP_arm64.cpp ------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "RegisterContextKDP_arm64.h" - -#include "ProcessKDP.h" -#include "ThreadKDP.h" - -using namespace lldb; -using namespace lldb_private; - -RegisterContextKDP_arm64::RegisterContextKDP_arm64(ThreadKDP &thread, - uint32_t concrete_frame_idx) - : RegisterContextDarwin_arm64(thread, concrete_frame_idx), - m_kdp_thread(thread) {} - -RegisterContextKDP_arm64::~RegisterContextKDP_arm64() {} - -int RegisterContextKDP_arm64::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoWriteGPR(lldb::tid_t tid, int flavor, - const GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoWriteFPU(lldb::tid_t tid, int flavor, - const FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoWriteEXC(lldb::tid_t tid, int flavor, - const EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_arm64::DoWriteDBG(lldb::tid_t tid, int flavor, - const DBG &dbg) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, DBGRegSet, &dbg, sizeof(dbg), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h deleted file mode 100644 index be4038ba96eaf..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h +++ /dev/null @@ -1,45 +0,0 @@ -//===-- RegisterContextKDP_arm64.h --------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextKDP_arm64_h_ -#define liblldb_RegisterContextKDP_arm64_h_ - - -#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h" - -class ThreadKDP; - -class RegisterContextKDP_arm64 : public RegisterContextDarwin_arm64 { -public: - RegisterContextKDP_arm64(ThreadKDP &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextKDP_arm64(); - -protected: - virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); - - int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg); - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); - - int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg); - - ThreadKDP &m_kdp_thread; -}; - -#endif // liblldb_RegisterContextKDP_arm64_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp deleted file mode 100644 index 096aa0f95d009..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===-- RegisterContextKDP_i386.cpp -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "RegisterContextKDP_i386.h" -#include "ProcessKDP.h" -#include "ThreadKDP.h" - -using namespace lldb; -using namespace lldb_private; - -RegisterContextKDP_i386::RegisterContextKDP_i386(ThreadKDP &thread, - uint32_t concrete_frame_idx) - : RegisterContextDarwin_i386(thread, concrete_frame_idx), - m_kdp_thread(thread) {} - -RegisterContextKDP_i386::~RegisterContextKDP_i386() {} - -int RegisterContextKDP_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_i386::DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_i386::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_i386::DoWriteGPR(lldb::tid_t tid, int flavor, - const GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_i386::DoWriteFPU(lldb::tid_t tid, int flavor, - const FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_i386::DoWriteEXC(lldb::tid_t tid, int flavor, - const EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h deleted file mode 100644 index 699d5fabe1570..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h +++ /dev/null @@ -1,39 +0,0 @@ -//===-- RegisterContextKDP_i386.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextKDP_i386_h_ -#define liblldb_RegisterContextKDP_i386_h_ - -#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" - -class ThreadKDP; - -class RegisterContextKDP_i386 : public RegisterContextDarwin_i386 { -public: - RegisterContextKDP_i386(ThreadKDP &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextKDP_i386(); - -protected: - virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); - - ThreadKDP &m_kdp_thread; -}; - -#endif // liblldb_RegisterContextKDP_i386_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp deleted file mode 100644 index 9d85145f2eaf2..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp +++ /dev/null @@ -1,118 +0,0 @@ -//===-- RegisterContextKDP_x86_64.cpp ---------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "RegisterContextKDP_x86_64.h" -#include "ProcessKDP.h" -#include "ThreadKDP.h" - -using namespace lldb; -using namespace lldb_private; - -RegisterContextKDP_x86_64::RegisterContextKDP_x86_64( - ThreadKDP &thread, uint32_t concrete_frame_idx) - : RegisterContextDarwin_x86_64(thread, concrete_frame_idx), - m_kdp_thread(thread) {} - -RegisterContextKDP_x86_64::~RegisterContextKDP_x86_64() {} - -int RegisterContextKDP_x86_64::DoReadGPR(lldb::tid_t tid, int flavor, - GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_x86_64::DoReadFPU(lldb::tid_t tid, int flavor, - FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_x86_64::DoReadEXC(lldb::tid_t tid, int flavor, - EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestReadRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_x86_64::DoWriteGPR(lldb::tid_t tid, int flavor, - const GPR &gpr) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, GPRRegSet, &gpr, sizeof(gpr), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_x86_64::DoWriteFPU(lldb::tid_t tid, int flavor, - const FPU &fpu) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, FPURegSet, &fpu, sizeof(fpu), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} - -int RegisterContextKDP_x86_64::DoWriteEXC(lldb::tid_t tid, int flavor, - const EXC &exc) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - Status error; - if (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .SendRequestWriteRegisters(tid, EXCRegSet, &exc, sizeof(exc), - error)) { - if (error.Success()) - return 0; - } - } - return -1; -} diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h deleted file mode 100644 index 9841ad77b0044..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h +++ /dev/null @@ -1,39 +0,0 @@ -//===-- RegisterContextKDP_x86_64.h -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextKDP_x86_64_h_ -#define liblldb_RegisterContextKDP_x86_64_h_ - -#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" - -class ThreadKDP; - -class RegisterContextKDP_x86_64 : public RegisterContextDarwin_x86_64 { -public: - RegisterContextKDP_x86_64(ThreadKDP &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextKDP_x86_64(); - -protected: - virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr); - - int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu); - - int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc); - - int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr); - - int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu); - - int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc); - - ThreadKDP &m_kdp_thread; -}; - -#endif // liblldb_RegisterContextKDP_x86_64_h_ diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp deleted file mode 100644 index 6f26acd0b8aa7..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ /dev/null @@ -1,170 +0,0 @@ -//===-- ThreadKDP.cpp -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ThreadKDP.h" - -#include "lldb/Host/SafeMachO.h" - -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Unwind.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/StreamString.h" - -#include "Plugins/Process/Utility/StopInfoMachException.h" -#include "ProcessKDP.h" -#include "ProcessKDPLog.h" -#include "RegisterContextKDP_arm.h" -#include "RegisterContextKDP_arm64.h" -#include "RegisterContextKDP_i386.h" -#include "RegisterContextKDP_x86_64.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Thread Registers -//---------------------------------------------------------------------- - -ThreadKDP::ThreadKDP(Process &process, lldb::tid_t tid) - : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), - m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS) { - Log *log = ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD); - LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID()); -} - -ThreadKDP::~ThreadKDP() { - Log *log = ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_THREAD); - LLDB_LOG(log, "this = {0}, tid = {1:x}", this, GetID()); - DestroyThread(); -} - -const char *ThreadKDP::GetName() { - if (m_thread_name.empty()) - return nullptr; - return m_thread_name.c_str(); -} - -const char *ThreadKDP::GetQueueName() { return nullptr; } - -void ThreadKDP::RefreshStateAfterStop() { - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do the - // right thing. - const bool force = false; - lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext()); - if (reg_ctx_sp) - reg_ctx_sp->InvalidateIfNeeded(force); -} - -bool ThreadKDP::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } - -void ThreadKDP::Dump(Log *log, uint32_t index) {} - -bool ThreadKDP::ShouldStop(bool &step_more) { return true; } -lldb::RegisterContextSP ThreadKDP::GetRegisterContext() { - if (!m_reg_context_sp) - m_reg_context_sp = CreateRegisterContextForFrame(nullptr); - return m_reg_context_sp; -} - -lldb::RegisterContextSP -ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) { - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) { - ProcessSP process_sp(CalculateProcess()); - if (process_sp) { - switch (static_cast<ProcessKDP *>(process_sp.get()) - ->GetCommunication() - .GetCPUType()) { - case llvm::MachO::CPU_TYPE_ARM: - reg_ctx_sp.reset(new RegisterContextKDP_arm(*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_ARM64: - reg_ctx_sp.reset( - new RegisterContextKDP_arm64(*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_I386: - reg_ctx_sp.reset( - new RegisterContextKDP_i386(*this, concrete_frame_idx)); - break; - case llvm::MachO::CPU_TYPE_X86_64: - reg_ctx_sp.reset( - new RegisterContextKDP_x86_64(*this, concrete_frame_idx)); - break; - default: - llvm_unreachable("Add CPU type support in KDP"); - } - } - } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); - } - return reg_ctx_sp; -} - -bool ThreadKDP::CalculateStopInfo() { - ProcessSP process_sp(GetProcess()); - if (process_sp) { - if (m_cached_stop_info_sp) { - SetStopInfo(m_cached_stop_info_sp); - } else { - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP)); - } - return true; - } - return false; -} - -void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION( - const DataExtractor &exc_reply_packet) { - lldb::offset_t offset = 0; - uint8_t reply_command = exc_reply_packet.GetU8(&offset); - if (reply_command == CommunicationKDP::KDP_EXCEPTION) { - offset = 8; - const uint32_t count = exc_reply_packet.GetU32(&offset); - if (count >= 1) { - // const uint32_t cpu = exc_reply_packet.GetU32 (&offset); - offset += 4; // Skip the useless CPU field - const uint32_t exc_type = exc_reply_packet.GetU32(&offset); - const uint32_t exc_code = exc_reply_packet.GetU32(&offset); - const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset); - // We have to make a copy of the stop info because the thread list will - // iterate through the threads and clear all stop infos.. - - // Let the StopInfoMachException::CreateStopReasonWithMachException() - // function update the PC if needed as we might hit a software breakpoint - // and need to decrement the PC (i386 and x86_64 need this) and KDP - // doesn't do this for us. - const bool pc_already_adjusted = false; - const bool adjust_pc_if_needed = true; - - m_cached_stop_info_sp = - StopInfoMachException::CreateStopReasonWithMachException( - *this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted, - adjust_pc_if_needed); - } - } -} diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h deleted file mode 100644 index ea517b4254fc9..0000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.h +++ /dev/null @@ -1,77 +0,0 @@ -//===-- ThreadKDP.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ThreadKDP_h_ -#define liblldb_ThreadKDP_h_ - -#include <string> - -#include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" - -class ProcessKDP; - -class ThreadKDP : public lldb_private::Thread { -public: - ThreadKDP(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~ThreadKDP(); - - virtual void RefreshStateAfterStop(); - - virtual const char *GetName(); - - virtual const char *GetQueueName(); - - virtual lldb::RegisterContextSP GetRegisterContext(); - - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame); - - void Dump(lldb_private::Log *log, uint32_t index); - - static bool ThreadIDIsValid(lldb::tid_t thread); - - bool ShouldStop(bool &step_more); - - const char *GetBasicInfoAsString(); - - void SetName(const char *name) { - if (name && name[0]) - m_thread_name.assign(name); - else - m_thread_name.clear(); - } - - lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; } - - void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) { - m_thread_dispatch_qaddr = thread_dispatch_qaddr; - } - - void SetStopInfoFrom_KDP_EXCEPTION( - const lldb_private::DataExtractor &exc_reply_packet); - -protected: - friend class ProcessKDP; - - //------------------------------------------------------------------ - // Member variables. - //------------------------------------------------------------------ - std::string m_thread_name; - std::string m_dispatch_queue_name; - lldb::addr_t m_thread_dispatch_qaddr; - lldb::StopInfoSP m_cached_stop_info_sp; - //------------------------------------------------------------------ - // Protected member functions. - //------------------------------------------------------------------ - virtual bool CalculateStopInfo(); -}; - -#endif // liblldb_ThreadKDP_h_ diff --git a/source/Plugins/Process/NetBSD/CMakeLists.txt b/source/Plugins/Process/NetBSD/CMakeLists.txt deleted file mode 100644 index e131e6d70468b..0000000000000 --- a/source/Plugins/Process/NetBSD/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_lldb_library(lldbPluginProcessNetBSD PLUGIN - NativeProcessNetBSD.cpp - NativeRegisterContextNetBSD.cpp - NativeRegisterContextNetBSD_x86_64.cpp - NativeThreadNetBSD.cpp - - LINK_LIBS - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessPOSIX - lldbPluginProcessUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/POSIX/CMakeLists.txt b/source/Plugins/Process/POSIX/CMakeLists.txt deleted file mode 100644 index f058e01c74394..0000000000000 --- a/source/Plugins/Process/POSIX/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginProcessPOSIX PLUGIN - CrashReason.cpp - ProcessMessage.cpp - ProcessPOSIXLog.cpp - - LINK_LIBS - lldbInterpreter - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt deleted file mode 100644 index e36ce4dec98a8..0000000000000 --- a/source/Plugins/Process/Utility/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -add_lldb_library(lldbPluginProcessUtility PLUGIN - DynamicRegisterInfo.cpp - FreeBSDSignals.cpp - GDBRemoteSignals.cpp - HistoryThread.cpp - HistoryUnwind.cpp - InferiorCallPOSIX.cpp - LinuxProcMaps.cpp - LinuxSignals.cpp - MipsLinuxSignals.cpp - NativeRegisterContextRegisterInfo.cpp - NetBSDSignals.cpp - RegisterContextDarwin_arm.cpp - RegisterContextDarwin_arm64.cpp - RegisterContextDarwin_i386.cpp - RegisterContextDarwin_x86_64.cpp - RegisterContextDummy.cpp - RegisterContextFreeBSD_i386.cpp - RegisterContextFreeBSD_mips64.cpp - RegisterContextFreeBSD_powerpc.cpp - RegisterContextFreeBSD_x86_64.cpp - RegisterContextHistory.cpp - RegisterContextLinux_i386.cpp - RegisterContextLinux_x86_64.cpp - RegisterContextLinux_mips64.cpp - RegisterContextLinux_mips.cpp - RegisterContextLinux_s390x.cpp - RegisterContextLLDB.cpp - RegisterContextMacOSXFrameBackchain.cpp - RegisterContextMach_arm.cpp - RegisterContextMach_i386.cpp - RegisterContextMach_x86_64.cpp - RegisterContextMemory.cpp - RegisterContextNetBSD_x86_64.cpp - RegisterContextOpenBSD_i386.cpp - RegisterContextOpenBSD_x86_64.cpp - RegisterContextPOSIX_arm.cpp - RegisterContextPOSIX_arm64.cpp - RegisterContextPOSIX_mips64.cpp - RegisterContextPOSIX_powerpc.cpp - RegisterContextPOSIX_ppc64le.cpp - RegisterContextPOSIX_s390x.cpp - RegisterContextPOSIX_x86.cpp - RegisterContextThreadMemory.cpp - RegisterInfoPOSIX_arm.cpp - RegisterInfoPOSIX_arm64.cpp - RegisterInfoPOSIX_ppc64le.cpp - StopInfoMachException.cpp - ThreadMemory.cpp - UnwindLLDB.cpp - UnwindMacOSXFrameBackchain.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbDataFormatters - lldbExpression - lldbHost - lldbSymbol - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/Windows/Common/CMakeLists.txt b/source/Plugins/Process/Windows/Common/CMakeLists.txt deleted file mode 100644 index 0926290861833..0000000000000 --- a/source/Plugins/Process/Windows/Common/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -set(PROC_WINDOWS_COMMON_SOURCES - DebuggerThread.cpp - LocalDebugDelegate.cpp - ProcessWindows.cpp - ProcessWindowsLog.cpp - RegisterContextWindows.cpp - TargetThreadWindows.cpp - ) - -if (CMAKE_SIZEOF_VOID_P EQUAL 4) - set(PROC_WINDOWS_COMMON_SOURCES ${PROC_WINDOWS_COMMON_SOURCES} - x86/RegisterContextWindows_x86.cpp - ) -elseif (CMAKE_SIZEOF_VOID_P EQUAL 8) - set(PROC_WINDOWS_COMMON_SOURCES ${PROC_WINDOWS_COMMON_SOURCES} - x64/RegisterContextWindows_x64.cpp - ) -endif() - -add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN - ${PROC_WINDOWS_COMMON_SOURCES} - - LINK_LIBS - lldbCore - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - ws2_32 - rpcrt4 - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp deleted file mode 100644 index 81ec25871c577..0000000000000 --- a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ /dev/null @@ -1,520 +0,0 @@ -//===-- DebuggerThread.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DebuggerThread.h" -#include "ExceptionRecord.h" -#include "IDebugDelegate.h" - -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/windows/HostProcessWindows.h" -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/ProcessLauncherWindows.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Predicate.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { -struct DebugLaunchContext { - DebugLaunchContext(DebuggerThread *thread, - const ProcessLaunchInfo &launch_info) - : m_thread(thread), m_launch_info(launch_info) {} - DebuggerThread *m_thread; - ProcessLaunchInfo m_launch_info; -}; - -struct DebugAttachContext { - DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, - const ProcessAttachInfo &attach_info) - : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} - DebuggerThread *m_thread; - lldb::pid_t m_pid; - ProcessAttachInfo m_attach_info; -}; -} // namespace - -DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) - : m_debug_delegate(debug_delegate), m_pid_to_detach(0), - m_is_shutting_down(false) { - m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); -} - -DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } - -Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); - - Status error; - DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - HostThread slave_thread(ThreadLauncher::LaunchThread( - "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, - context, &error)); - - if (!error.Success()) - LLDB_LOG(log, "couldn't launch debugger thread. {0}", error); - - return error; -} - -Status DebuggerThread::DebugAttach(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "attaching to '{0}'", pid); - - Status error; - DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); - HostThread slave_thread(ThreadLauncher::LaunchThread( - "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, - context, &error)); - - if (!error.Success()) - LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, error); - - return error; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { - DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); - lldb::thread_result_t result = - context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); - delete context; - return result; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { - DebugAttachContext *context = static_cast<DebugAttachContext *>(data); - lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( - context->m_pid, context->m_attach_info); - delete context; - return result; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( - const ProcessLaunchInfo &launch_info) { - // Grab a shared_ptr reference to this so that we know it won't get deleted - // until after the thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "preparing to launch '{0}' on background thread.", - launch_info.GetExecutableFile().GetPath()); - - Status error; - ProcessLauncherWindows launcher; - HostProcess process(launcher.LaunchProcess(launch_info, error)); - // If we couldn't create the process, notify waiters immediately. Otherwise - // enter the debug loop and wait until we get the create process debug - // notification. Note that if the process was created successfully, we can - // throw away the process handle we got from CreateProcess because Windows - // will give us another (potentially more useful?) handle when it sends us - // the CREATE_PROCESS_DEBUG_EVENT. - if (error.Success()) - DebugLoop(); - else - m_debug_delegate->OnDebuggerError(error, 0); - - return 0; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( - lldb::pid_t pid, const ProcessAttachInfo &attach_info) { - // Grab a shared_ptr reference to this so that we know it won't get deleted - // until after the thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.", - pid); - - if (!DebugActiveProcess((DWORD)pid)) { - Status error(::GetLastError(), eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, 0); - return 0; - } - - // The attach was successful, enter the debug loop. From here on out, this - // is no different than a create process operation, so all the same comments - // in DebugLaunch should apply from this point out. - DebugLoop(); - - return 0; -} - -Status DebuggerThread::StopDebugging(bool terminate) { - Status error; - - lldb::pid_t pid = m_process.GetProcessId(); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid); - - // Set m_is_shutting_down to true if it was false. Return if it was already - // true. - bool expected = false; - if (!m_is_shutting_down.compare_exchange_strong(expected, true)) - return error; - - // Make a copy of the process, since the termination sequence will reset - // DebuggerThread's internal copy and it needs to remain open for the Wait - // operation. - HostProcess process_copy = m_process; - lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); - - if (terminate) { - if (handle != nullptr && handle != LLDB_INVALID_PROCESS) { - // Initiate the termination before continuing the exception, so that the - // next debug event we get is the exit process event, and not some other - // event. - BOOL terminate_suceeded = TerminateProcess(handle, 0); - LLDB_LOG(log, - "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", - handle, pid, terminate_suceeded); - } else { - LLDB_LOG(log, - "NOT calling TerminateProcess because the inferior is not valid " - "({0}, 0) (inferior={1})", - handle, pid); - } - } - - // If we're stuck waiting for an exception to continue (e.g. the user is at a - // breakpoint messing around in the debugger), continue it now. But only - // AFTER calling TerminateProcess to make sure that the very next call to - // WaitForDebugEvent is an exit process event. - if (m_active_exception.get()) { - LLDB_LOG(log, "masking active exception"); - ContinueAsyncException(ExceptionResult::MaskException); - } - - if (!terminate) { - // Indicate that we want to detach. - m_pid_to_detach = GetProcess().GetProcessId(); - - // Force a fresh break so that the detach can happen from the debugger - // thread. - if (!::DebugBreakProcess( - GetProcess().GetNativeProcess().GetSystemHandle())) { - error.SetError(::GetLastError(), eErrorTypeWin32); - } - } - - LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid); - - DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); - if (wait_result != WAIT_OBJECT_0) { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}", - m_debugging_ended_event, wait_result); - } else - LLDB_LOG(log, "detach from process {0} completed successfully.", pid); - - if (!error.Success()) { - LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}", - pid, error); - } - return error; -} - -void DebuggerThread::ContinueAsyncException(ExceptionResult result) { - if (!m_active_exception.get()) - return; - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | - WINDOWS_LOG_EXCEPTION); - LLDB_LOG(log, "broadcasting for inferior process {0}.", - m_process.GetProcessId()); - - m_active_exception.reset(); - m_exception_pred.SetValue(result, eBroadcastAlways); -} - -void DebuggerThread::FreeProcessHandles() { - m_process = HostProcess(); - m_main_thread = HostThread(); - if (m_image_file) { - ::CloseHandle(m_image_file); - m_image_file = nullptr; - } -} - -void DebuggerThread::DebugLoop() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - DEBUG_EVENT dbe = {}; - bool should_debug = true; - LLDB_LOGV(log, "Entering WaitForDebugEvent loop"); - while (should_debug) { - LLDB_LOGV(log, "Calling WaitForDebugEvent"); - BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); - if (wait_result) { - DWORD continue_status = DBG_CONTINUE; - switch (dbe.dwDebugEventCode) { - default: - llvm_unreachable("Unhandle debug event code!"); - case EXCEPTION_DEBUG_EVENT: { - ExceptionResult status = - HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); - - if (status == ExceptionResult::MaskException) - continue_status = DBG_CONTINUE; - else if (status == ExceptionResult::SendToApplication) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - - break; - } - case CREATE_THREAD_DEBUG_EVENT: - continue_status = - HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); - break; - case CREATE_PROCESS_DEBUG_EVENT: - continue_status = - HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); - break; - case EXIT_THREAD_DEBUG_EVENT: - continue_status = - HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); - break; - case EXIT_PROCESS_DEBUG_EVENT: - continue_status = - HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); - should_debug = false; - break; - case LOAD_DLL_DEBUG_EVENT: - continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); - break; - case UNLOAD_DLL_DEBUG_EVENT: - continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); - break; - case OUTPUT_DEBUG_STRING_EVENT: - continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); - break; - case RIP_EVENT: - continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); - if (dbe.u.RipInfo.dwType == SLE_ERROR) - should_debug = false; - break; - } - - LLDB_LOGV(log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.", - dbe.dwProcessId, dbe.dwThreadId, continue_status, - ::GetCurrentThreadId()); - - ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); - - if (m_detached) { - should_debug = false; - } - } else { - LLDB_LOG(log, "returned FALSE from WaitForDebugEvent. Error = {0}", - ::GetLastError()); - - should_debug = false; - } - } - FreeProcessHandles(); - - LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting."); - ::SetEvent(m_debugging_ended_event); -} - -ExceptionResult -DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION); - if (m_is_shutting_down) { - // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic - // exception that - // we use simply to wake up the DebuggerThread so that we can close out the - // debug loop. - if (m_pid_to_detach != 0 && - info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}", - m_pid_to_detach.load()); - ::DebugActiveProcessStop(m_pid_to_detach); - m_detached = true; - } - - // Don't perform any blocking operations while we're shutting down. That - // will cause TerminateProcess -> WaitForSingleObject to time out. - return ExceptionResult::SendToApplication; - } - - bool first_chance = (info.dwFirstChance != 0); - - m_active_exception.reset( - new ExceptionRecord(info.ExceptionRecord, thread_id)); - LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}", - first_chance ? "first" : "second", - info.ExceptionRecord.ExceptionCode, thread_id); - - ExceptionResult result = - m_debug_delegate->OnDebugException(first_chance, *m_active_exception); - m_exception_pred.SetValue(result, eBroadcastNever); - - LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger"); - result = *m_exception_pred.WaitForValueNotEqualTo( - ExceptionResult::BreakInDebugger); - - LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue()); - return result; -} - -DWORD -DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id, - m_process.GetProcessId()); - HostThread thread(info.hThread); - thread.GetNativeThread().SetOwnsHandle(false); - m_debug_delegate->OnCreateThread(thread); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS); - uint32_t process_id = ::GetProcessId(info.hProcess); - - LLDB_LOG(log, "process {0} spawned", process_id); - - std::string thread_name; - llvm::raw_string_ostream name_stream(thread_name); - name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; - name_stream.flush(); - llvm::set_thread_name(thread_name); - - // info.hProcess and info.hThread are closed automatically by Windows when - // EXIT_PROCESS_DEBUG_EVENT is received. - m_process = HostProcess(info.hProcess); - ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); - m_main_thread = HostThread(info.hThread); - m_main_thread.GetNativeThread().SetOwnsHandle(false); - m_image_file = info.hFile; - - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); - m_debug_delegate->OnDebuggerConnected(load_addr); - - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id, - info.dwExitCode, m_process.GetProcessId()); - m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(), - info.dwExitCode); - - m_debug_delegate->OnExitProcess(info.dwExitCode); - - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - if (info.hFile == nullptr) { - // Not sure what this is, so just ignore it. - LLDB_LOG(log, "Warning: Inferior {0} has a NULL file handle, returning...", - m_process.GetProcessId()); - return DBG_CONTINUE; - } - - std::vector<wchar_t> buffer(1); - DWORD required_size = - GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); - if (required_size > 0) { - buffer.resize(required_size + 1); - required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], - required_size, VOLUME_NAME_DOS); - std::string path_str_utf8; - llvm::convertWideToUTF8(buffer.data(), path_str_utf8); - llvm::StringRef path_str = path_str_utf8; - const char *path = path_str.data(); - if (path_str.startswith("\\\\?\\")) - path += 4; - - FileSpec file_spec(path); - ModuleSpec module_spec(file_spec); - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); - - LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", - m_process.GetProcessId(), path, info.lpBaseOfDll); - - m_debug_delegate->OnLoadDll(module_spec, load_addr); - } else { - LLDB_LOG( - log, - "Inferior {0} - Error {1} occurred calling GetFinalPathNameByHandle", - m_process.GetProcessId(), ::GetLastError()); - } - // Windows does not automatically close info.hFile, so we need to do it. - ::CloseHandle(info.hFile); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.", - m_process.GetProcessId(), info.lpBaseOfDll); - - m_debug_delegate->OnUnloadDll( - reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, - DWORD thread_id) { - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}", - info.dwError, info.dwType, m_process.GetProcessId(), thread_id); - - Status error(info.dwError, eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, info.dwType); - - return DBG_CONTINUE; -} diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.h b/source/Plugins/Process/Windows/Common/DebuggerThread.h deleted file mode 100644 index 047d3ccb7296b..0000000000000 --- a/source/Plugins/Process/Windows/Common/DebuggerThread.h +++ /dev/null @@ -1,106 +0,0 @@ -//===-- DebuggerThread.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_DebuggerThread_H_ -#define liblldb_Plugins_Process_Windows_DebuggerThread_H_ - -#include <atomic> -#include <memory> - -#include "ForwardDecl.h" -#include "lldb/Host/HostProcess.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/Predicate.h" - -namespace lldb_private { - -//---------------------------------------------------------------------- -// DebuggerThread -// -// Debugs a single process, notifying listeners as appropriate when interesting -// things occur. -//---------------------------------------------------------------------- -class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> { -public: - DebuggerThread(DebugDelegateSP debug_delegate); - virtual ~DebuggerThread(); - - Status DebugLaunch(const ProcessLaunchInfo &launch_info); - Status DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info); - - HostProcess GetProcess() const { return m_process; } - HostThread GetMainThread() const { return m_main_thread; } - std::weak_ptr<ExceptionRecord> GetActiveException() { - return m_active_exception; - } - - Status StopDebugging(bool terminate); - - void ContinueAsyncException(ExceptionResult result); - -private: - void FreeProcessHandles(); - void DebugLoop(); - ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id); - DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, - DWORD thread_id); - DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id); - DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id); - - DebugDelegateSP m_debug_delegate; - - HostProcess m_process; // The process being debugged. - HostThread m_main_thread; // The main thread of the inferior. - - // The image file of the process being debugged. - HANDLE m_image_file = nullptr; - - // The current exception waiting to be handled - ExceptionRecordSP m_active_exception; - - // A predicate which gets signalled when an exception is finished processing - // and the debug loop can be continued. - Predicate<ExceptionResult> m_exception_pred; - - // An event which gets signalled by the debugger thread when it exits the - // debugger loop and is detached from the inferior. - HANDLE m_debugging_ended_event = nullptr; - - // Signals the loop to detach from the process (specified by pid). - std::atomic<DWORD> m_pid_to_detach; - - // Signals the debug loop to stop processing certain types of events that - // block shutdown. - std::atomic<bool> m_is_shutting_down; - - // Indicates we've detached from the inferior process and the debug loop can - // exit. - bool m_detached = false; - - static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data); - lldb::thread_result_t - DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info); - static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data); - lldb::thread_result_t - DebuggerThreadAttachRoutine(lldb::pid_t pid, - const ProcessAttachInfo &launch_info); -}; -} -#endif diff --git a/source/Plugins/Process/Windows/Common/ExceptionRecord.h b/source/Plugins/Process/Windows/Common/ExceptionRecord.h deleted file mode 100644 index 1eec85d52c264..0000000000000 --- a/source/Plugins/Process/Windows/Common/ExceptionRecord.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- ExceptionRecord.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_ExceptionRecord_H_ -#define liblldb_Plugins_Process_Windows_ExceptionRecord_H_ - -#include "lldb/Host/windows/windows.h" -#include "lldb/lldb-forward.h" -#include <dbghelp.h> - -#include <memory> -#include <vector> - -namespace lldb_private { - -//---------------------------------------------------------------------- -// ExceptionRecord -// -// ExceptionRecord defines an interface which allows implementors to receive -// notification of events that happen in a debugged process. -//---------------------------------------------------------------------- -class ExceptionRecord { -public: - ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) { - m_code = record.ExceptionCode; - m_continuable = (record.ExceptionFlags == 0); - if (record.ExceptionRecord) - m_next_exception.reset( - new ExceptionRecord(*record.ExceptionRecord, thread_id)); - m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress); - m_thread_id = thread_id; - m_arguments.assign(record.ExceptionInformation, - record.ExceptionInformation + record.NumberParameters); - } - - // MINIDUMP_EXCEPTIONs are almost identical to EXCEPTION_RECORDs. - ExceptionRecord(const MINIDUMP_EXCEPTION &record, lldb::tid_t thread_id) - : m_code(record.ExceptionCode), m_continuable(record.ExceptionFlags == 0), - m_next_exception(nullptr), - m_exception_addr(static_cast<lldb::addr_t>(record.ExceptionAddress)), - m_thread_id(thread_id), - m_arguments(record.ExceptionInformation, - record.ExceptionInformation + record.NumberParameters) { - // Set up link to nested exception. - if (record.ExceptionRecord) { - m_next_exception.reset(new ExceptionRecord( - *reinterpret_cast<const MINIDUMP_EXCEPTION *>(record.ExceptionRecord), - thread_id)); - } - } - - virtual ~ExceptionRecord() {} - - DWORD - GetExceptionCode() const { return m_code; } - bool IsContinuable() const { return m_continuable; } - const ExceptionRecord *GetNextException() const { - return m_next_exception.get(); - } - lldb::addr_t GetExceptionAddress() const { return m_exception_addr; } - - lldb::tid_t GetThreadID() const { return m_thread_id; } - -private: - DWORD m_code; - bool m_continuable; - std::shared_ptr<ExceptionRecord> m_next_exception; - lldb::addr_t m_exception_addr; - lldb::tid_t m_thread_id; - std::vector<ULONG_PTR> m_arguments; -}; -} - -#endif diff --git a/source/Plugins/Process/Windows/Common/ForwardDecl.h b/source/Plugins/Process/Windows/Common/ForwardDecl.h deleted file mode 100644 index ce2af3ca4111a..0000000000000 --- a/source/Plugins/Process/Windows/Common/ForwardDecl.h +++ /dev/null @@ -1,42 +0,0 @@ -//===-- ForwardDecl.h -------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_ForwardDecl_H_ -#define liblldb_Plugins_Process_Windows_ForwardDecl_H_ - -#include <memory> - -// ExceptionResult is returned by the debug delegate to specify how it processed -// the exception. -enum class ExceptionResult { - BreakInDebugger, // Break in the debugger and give the user a chance to - // interact with - // the program before continuing. - MaskException, // Eat the exception and don't let the application know it - // occurred. - SendToApplication // Send the exception to the application to be handled as if - // there were - // no debugger attached. -}; - -namespace lldb_private { - -class ProcessWindows; - -class IDebugDelegate; -class DebuggerThread; -class ExceptionRecord; - -typedef std::shared_ptr<IDebugDelegate> DebugDelegateSP; -typedef std::shared_ptr<DebuggerThread> DebuggerThreadSP; -typedef std::shared_ptr<ExceptionRecord> ExceptionRecordSP; -typedef std::unique_ptr<ExceptionRecord> ExceptionRecordUP; -} - -#endif diff --git a/source/Plugins/Process/Windows/Common/IDebugDelegate.h b/source/Plugins/Process/Windows/Common/IDebugDelegate.h deleted file mode 100644 index 73c285f1ecc79..0000000000000 --- a/source/Plugins/Process/Windows/Common/IDebugDelegate.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- IDebugDelegate.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_IDebugDelegate_H_ -#define liblldb_Plugins_Process_Windows_IDebugDelegate_H_ - -#include "ForwardDecl.h" -#include "lldb/lldb-forward.h" -#include "lldb/lldb-types.h" -#include <string> - -namespace lldb_private { -class Status; -class HostThread; - -//---------------------------------------------------------------------- -// IDebugDelegate -// -// IDebugDelegate defines an interface which allows implementors to receive -// notification of events that happen in a debugged process. -//---------------------------------------------------------------------- -class IDebugDelegate { -public: - virtual ~IDebugDelegate() {} - - virtual void OnExitProcess(uint32_t exit_code) = 0; - virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0; - virtual ExceptionResult OnDebugException(bool first_chance, - const ExceptionRecord &record) = 0; - virtual void OnCreateThread(const HostThread &thread) = 0; - virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0; - virtual void OnLoadDll(const ModuleSpec &module_spec, - lldb::addr_t module_addr) = 0; - virtual void OnUnloadDll(lldb::addr_t module_addr) = 0; - virtual void OnDebugString(const std::string &string) = 0; - virtual void OnDebuggerError(const Status &error, uint32_t type) = 0; -}; -} - -#endif diff --git a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp b/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp deleted file mode 100644 index 92aa7e2678b95..0000000000000 --- a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- LocalDebugDelegate.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LocalDebugDelegate.h" -#include "ProcessWindows.h" - -using namespace lldb; -using namespace lldb_private; - -LocalDebugDelegate::LocalDebugDelegate(ProcessWP process) - : m_process(process) {} - -void LocalDebugDelegate::OnExitProcess(uint32_t exit_code) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnExitProcess(exit_code); -} - -void LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnDebuggerConnected(image_base); -} - -ExceptionResult -LocalDebugDelegate::OnDebugException(bool first_chance, - const ExceptionRecord &record) { - if (ProcessWindowsSP process = GetProcessPointer()) - return process->OnDebugException(first_chance, record); - else - return ExceptionResult::MaskException; -} - -void LocalDebugDelegate::OnCreateThread(const HostThread &thread) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnCreateThread(thread); -} - -void LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id, - uint32_t exit_code) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnExitThread(thread_id, exit_code); -} - -void LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec, - lldb::addr_t module_addr) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnLoadDll(module_spec, module_addr); -} - -void LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnUnloadDll(module_addr); -} - -void LocalDebugDelegate::OnDebugString(const std::string &string) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnDebugString(string); -} - -void LocalDebugDelegate::OnDebuggerError(const Status &error, uint32_t type) { - if (ProcessWindowsSP process = GetProcessPointer()) - process->OnDebuggerError(error, type); -} - -ProcessWindowsSP LocalDebugDelegate::GetProcessPointer() { - ProcessSP process = m_process.lock(); - return std::static_pointer_cast<ProcessWindows>(process); -} diff --git a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h b/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h deleted file mode 100644 index 2cb479ccce8ab..0000000000000 --- a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- LocalDebugDelegate.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_LocalDebugDelegate_H_ -#define liblldb_Plugins_Process_Windows_LocalDebugDelegate_H_ - -#include <memory> - -#include "IDebugDelegate.h" - -#include "lldb/lldb-forward.h" - -namespace lldb_private { - -class ProcessWindows; -typedef std::shared_ptr<ProcessWindows> ProcessWindowsSP; - -//---------------------------------------------------------------------- -// LocalDebugDelegate -// -// LocalDebugDelegate creates a connection between a ProcessWindows and the -// debug driver. This serves to decouple ProcessWindows from the debug -// driver. It would be possible to get a similar decoupling by just having -// ProcessWindows implement this interface directly. There are two reasons -// why we don't do this: -// -// 1) In the future when we add support for local debugging through LLGS, and we -// go through the Native*Protocol interface, it is likely we will need the -// additional flexibility provided by this sort of adapter pattern. -// 2) LLDB holds a shared_ptr to the ProcessWindows, and our driver thread -// needs access to it as well. To avoid a race condition, we want to make -// sure that we're also holding onto a shared_ptr. -// lldb_private::Process supports enable_shared_from_this, but that gives us -// a ProcessSP (which is exactly what we are trying to decouple from the -// driver), so this adapter serves as a way to transparently hold the -// ProcessSP while still keeping it decoupled from the driver. -//---------------------------------------------------------------------- -class LocalDebugDelegate : public IDebugDelegate { -public: - explicit LocalDebugDelegate(lldb::ProcessWP process); - - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, - const ExceptionRecord &record) override; - void OnCreateThread(const HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const lldb_private::ModuleSpec &module_spec, - lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &message) override; - void OnDebuggerError(const Status &error, uint32_t type) override; - -private: - ProcessWindowsSP GetProcessPointer(); - - lldb::ProcessWP m_process; -}; -} - -#endif diff --git a/source/Plugins/Process/Windows/Common/NtStructures.h b/source/Plugins/Process/Windows/Common/NtStructures.h deleted file mode 100644 index 6826b98c769e7..0000000000000 --- a/source/Plugins/Process/Windows/Common/NtStructures.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- NtStructures.h ------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_Common_NtStructures_h_ -#define liblldb_Plugins_Process_Windows_Common_NtStructures_h_ - -#include "lldb/Host/windows/windows.h" - -// This describes the layout of a TEB (Thread Environment Block) for a 64-bit -// process. It's adapted from the 32-bit TEB in winternl.h. Currently, we care -// only about the position of the TlsSlots. -struct TEB64 { - ULONG64 Reserved1[12]; - ULONG64 ProcessEnvironmentBlock; - ULONG64 Reserved2[399]; - BYTE Reserved3[1952]; - ULONG64 TlsSlots[64]; - BYTE Reserved4[8]; - ULONG64 Reserved5[26]; - ULONG64 ReservedForOle; // Windows 2000 only - ULONG64 Reserved6[4]; - ULONG64 TlsExpansionSlots; -}; - -#endif diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp deleted file mode 100644 index 3fe5ab7804cba..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ /dev/null @@ -1,1119 +0,0 @@ -//===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessWindows.h" - -// Windows includes -#include "lldb/Host/windows/windows.h" -#include <psapi.h> - -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/HostNativeProcessBase.h" -#include "lldb/Host/HostProcess.h" -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/State.h" - -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/raw_ostream.h" - -#include "DebuggerThread.h" -#include "ExceptionRecord.h" -#include "ForwardDecl.h" -#include "LocalDebugDelegate.h" -#include "ProcessWindowsLog.h" -#include "TargetThreadWindows.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { -std::string GetProcessExecutableName(HANDLE process_handle) { - std::vector<wchar_t> file_name; - DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit - DWORD copied = 0; - do { - file_name_size *= 2; - file_name.resize(file_name_size); - copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), - file_name_size); - } while (copied >= file_name_size); - file_name.resize(copied); - std::string result; - llvm::convertWideToUTF8(file_name.data(), result); - return result; -} - -std::string GetProcessExecutableName(DWORD pid) { - std::string file_name; - HANDLE process_handle = - ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (process_handle != NULL) { - file_name = GetProcessExecutableName(process_handle); - ::CloseHandle(process_handle); - } - return file_name; -} - -DWORD ConvertLldbToWinApiProtect(uint32_t protect) { - // We also can process a read / write permissions here, but if the debugger - // will make later a write into the allocated memory, it will fail. To get - // around it is possible inside DoWriteMemory to remember memory permissions, - // allow write, write and restore permissions, but for now we process only - // the executable permission. - // - // TODO: Process permissions other than executable - if (protect & ePermissionsExecutable) - return PAGE_EXECUTE_READWRITE; - - return PAGE_READWRITE; -} - -} // anonymous namespace - -namespace lldb_private { - -// We store a pointer to this class in the ProcessWindows, so that we don't -// expose Windows-specific types and implementation details from a public -// header file. -class ProcessWindowsData { -public: - ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) { - m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - - ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } - - Status m_launch_error; - DebuggerThreadSP m_debugger; - StopInfoSP m_pending_stop_info; - HANDLE m_initial_stop_event = nullptr; - bool m_initial_stop_received = false; - bool m_stop_at_entry; - std::map<lldb::tid_t, HostThread> m_new_threads; - std::set<lldb::tid_t> m_exited_threads; -}; - -ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const FileSpec *) { - return ProcessSP(new ProcessWindows(target_sp, listener_sp)); -} - -void ProcessWindows::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); - }); -} - -void ProcessWindows::Terminate() {} - -lldb_private::ConstString ProcessWindows::GetPluginNameStatic() { - static ConstString g_name("windows"); - return g_name; -} - -const char *ProcessWindows::GetPluginDescriptionStatic() { - return "Process plugin for Windows"; -} - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp) - : lldb_private::Process(target_sp, listener_sp) {} - -ProcessWindows::~ProcessWindows() {} - -size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) { - error.SetErrorString("GetSTDOUT unsupported on Windows"); - return 0; -} - -size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) { - error.SetErrorString("GetSTDERR unsupported on Windows"); - return 0; -} - -size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, - Status &error) { - error.SetErrorString("PutSTDIN unsupported on Windows"); - return 0; -} - -//------------------------------------------------------------------------------ -// ProcessInterface protocol. - -lldb_private::ConstString ProcessWindows::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ProcessWindows::GetPluginVersion() { return 1; } - -Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, - bp_site->GetID(), bp_site->GetLoadAddress()); - - Status error = EnableSoftwareBreakpoint(bp_site); - if (!error.Success()) - LLDB_LOG(log, "error: {0}", error); - return error; -} - -Status ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, - bp_site->GetID(), bp_site->GetLoadAddress()); - - Status error = DisableSoftwareBreakpoint(bp_site); - - if (!error.Success()) - LLDB_LOG(log, "error: {0}", error); - return error; -} - -Status ProcessWindows::DoDetach(bool keep_stopped) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire the lock only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which will - // also acquire the lock. Thus we have to release the lock before calling - // StopDebugging(). - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) { - LLDB_LOG(log, "state = {0}, but there is no active session.", - private_state); - return Status(); - } - - debugger_thread = m_session_data->m_debugger; - } - - Status error; - if (private_state != eStateExited && private_state != eStateDetached) { - LLDB_LOG(log, "detaching from process {0} while state = {1}.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - error = debugger_thread->StopDebugging(false); - if (error.Success()) { - SetPrivateState(eStateDetached); - } - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } else { - LLDB_LOG( - log, - "error: process {0} in state = {1}, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - } - - return error; -} - -Status ProcessWindows::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) { - // Even though m_session_data is accessed here, it is before a debugger - // thread has been kicked off. So there's no race conditions, and it - // shouldn't be necessary to acquire the mutex. - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - Status result; - - FileSpec working_dir = launch_info.GetWorkingDirectory(); - namespace fs = llvm::sys::fs; - if (working_dir) { - FileSystem::Instance().Resolve(working_dir); - if (!FileSystem::Instance().IsDirectory(working_dir)) { - result.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return result; - } - } - - if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { - StreamString stream; - stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can " - "only be used for debug launches.", - launch_info.GetExecutableFile().GetPath().c_str()); - std::string message = stream.GetString(); - result.SetErrorString(message.c_str()); - - LLDB_LOG(log, "error: {0}", message); - return result; - } - - bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); - m_session_data.reset(new ProcessWindowsData(stop_at_entry)); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - m_session_data->m_debugger.reset(new DebuggerThread(delegate)); - DebuggerThreadSP debugger = m_session_data->m_debugger; - - // Kick off the DebugLaunch asynchronously and wait for it to complete. - result = debugger->DebugLaunch(launch_info); - if (result.Fail()) { - LLDB_LOG(log, "failed launching '{0}'. {1}", - launch_info.GetExecutableFile().GetPath(), result); - return result; - } - - HostProcess process; - Status error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) { - LLDB_LOG(log, "failed launching '{0}'. {1}", - launch_info.GetExecutableFile().GetPath(), error); - return error; - } - - LLDB_LOG(log, "successfully launched '{0}'", - launch_info.GetExecutableFile().GetPath()); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the - // private state should already be set to eStateStopped as a result of - // hitting the initial breakpoint. If it was not set, the breakpoint should - // have already been resumed from and the private state should already be - // eStateRunning. - launch_info.SetProcessID(process.GetProcessId()); - SetID(process.GetProcessId()); - - return result; -} - -Status -ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - m_session_data.reset( - new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - DebuggerThreadSP debugger(new DebuggerThread(delegate)); - - m_session_data->m_debugger = debugger; - - DWORD process_id = static_cast<DWORD>(pid); - Status error = debugger->DebugAttach(process_id, attach_info); - if (error.Fail()) { - LLDB_LOG( - log, - "encountered an error occurred initiating the asynchronous attach. {0}", - error); - return error; - } - - HostProcess process; - error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) { - LLDB_LOG(log, - "encountered an error waiting for the debugger to connect. {0}", - error); - return error; - } - - LLDB_LOG(log, "successfully attached to process with pid={0}", process_id); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the - // private state should already be set to eStateStopped as a result of - // hitting the initial breakpoint. If it was not set, the breakpoint should - // have already been resumed from and the private state should already be - // eStateRunning. - SetID(process.GetProcessId()); - return error; -} - -Status ProcessWindows::DoResume() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - llvm::sys::ScopedLock lock(m_mutex); - Status error; - - StateType private_state = GetPrivateState(); - if (private_state == eStateStopped || private_state == eStateCrashed) { - LLDB_LOG(log, "process {0} is in state {1}. Resuming...", - m_session_data->m_debugger->GetProcess().GetProcessId(), - GetPrivateState()); - - ExceptionRecordSP active_exception = - m_session_data->m_debugger->GetActiveException().lock(); - if (active_exception) { - // Resume the process and continue processing debug events. Mask the - // exception so that from the process's view, there is no indication that - // anything happened. - m_session_data->m_debugger->ContinueAsyncException( - ExceptionResult::MaskException); - } - - LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize()); - - bool failed = false; - for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) { - auto thread = std::static_pointer_cast<TargetThreadWindows>( - m_thread_list.GetThreadAtIndex(i)); - Status result = thread->DoResume(); - if (result.Fail()) { - failed = true; - LLDB_LOG( - log, - "Trying to resume thread at index {0}, but failed with error {1}.", - i, result); - } - } - - if (failed) { - error.SetErrorString("ProcessWindows::DoResume failed"); - return error; - } else { - SetPrivateState(eStateRunning); - } - } else { - LLDB_LOG(log, "error: process {0} is in state {1}. Returning...", - m_session_data->m_debugger->GetProcess().GetProcessId(), - GetPrivateState()); - } - return error; -} - -Status ProcessWindows::DoDestroy() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire this lock inside an inner scope, only long enough to get the - // DebuggerThread. StopDebugging() will trigger a call back into - // ProcessWindows which will acquire the lock again, so we need to not - // deadlock. - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) { - LLDB_LOG(log, "warning: state = {0}, but there is no active session.", - private_state); - return Status(); - } - - debugger_thread = m_session_data->m_debugger; - } - - Status error; - if (private_state != eStateExited && private_state != eStateDetached) { - LLDB_LOG(log, "Shutting down process {0} while state = {1}.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - error = debugger_thread->StopDebugging(true); - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } else { - LLDB_LOG(log, "cannot destroy process {0} while state = {1}", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - } - - return error; -} - -Status ProcessWindows::DoHalt(bool &caused_stop) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - Status error; - StateType state = GetPrivateState(); - if (state == eStateStopped) - caused_stop = false; - else { - llvm::sys::ScopedLock lock(m_mutex); - caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() - .GetNativeProcess() - .GetSystemHandle()); - if (!caused_stop) { - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error); - } - } - return error; -} - -void ProcessWindows::DidLaunch() { - ArchSpec arch_spec; - DidAttach(arch_spec); -} - -void ProcessWindows::DidAttach(ArchSpec &arch_spec) { - llvm::sys::ScopedLock lock(m_mutex); - - // The initial stop won't broadcast the state change event, so account for - // that here. - if (m_session_data && GetPrivateState() == eStateStopped && - m_session_data->m_stop_at_entry) - RefreshStateAfterStop(); -} - -void ProcessWindows::RefreshStateAfterStop() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); - llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) { - LLDB_LOG(log, "no active session. Returning..."); - return; - } - - m_thread_list.RefreshStateAfterStop(); - - std::weak_ptr<ExceptionRecord> exception_record = - m_session_data->m_debugger->GetActiveException(); - ExceptionRecordSP active_exception = exception_record.lock(); - if (!active_exception) { - LLDB_LOG(log, - "there is no active exception in process {0}. Why is the " - "process stopped?", - m_session_data->m_debugger->GetProcess().GetProcessId()); - return; - } - - StopInfoSP stop_info; - m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - ThreadSP stop_thread = m_thread_list.GetSelectedThread(); - if (!stop_thread) - return; - - switch (active_exception->GetExceptionCode()) { - case EXCEPTION_SINGLE_STEP: { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - const uint64_t pc = register_context->GetPC(); - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site && site->ValidForThisThread(stop_thread.get())) { - LLDB_LOG(log, - "Single-stepped onto a breakpoint in process {0} at " - "address {1:x} with breakpoint site {2}", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, - site->GetID()); - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, - site->GetID()); - stop_thread->SetStopInfo(stop_info); - } else { - LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID()); - stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); - stop_thread->SetStopInfo(stop_info); - } - return; - } - - case EXCEPTION_BREAKPOINT: { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - - // The current EIP is AFTER the BP opcode, which is one byte. - uint64_t pc = register_context->GetPC() - 1; - - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site) { - LLDB_LOG(log, - "detected breakpoint in process {0} at address {1:x} with " - "breakpoint site {2}", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, - site->GetID()); - - if (site->ValidForThisThread(stop_thread.get())) { - LLDB_LOG(log, - "Breakpoint site {0} is valid for this thread ({1:x}), " - "creating stop info.", - site->GetID(), stop_thread->GetID()); - - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( - *stop_thread, site->GetID()); - register_context->SetPC(pc); - } else { - LLDB_LOG(log, - "Breakpoint site {0} is not valid for this thread, " - "creating empty stop info.", - site->GetID()); - } - stop_thread->SetStopInfo(stop_info); - return; - } else { - // The thread hit a hard-coded breakpoint like an `int 3` or - // `__debugbreak()`. - LLDB_LOG(log, - "No breakpoint site matches for this thread. __debugbreak()? " - "Creating stop info with the exception."); - // FALLTHROUGH: We'll treat this as a generic exception record in the - // default case. - } - } - - default: { - std::string desc; - llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " - << llvm::format_hex(active_exception->GetExceptionCode(), 8) - << " encountered at address " - << llvm::format_hex(active_exception->GetExceptionAddress(), 8); - stop_info = StopInfo::CreateStopReasonWithException( - *stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); - LLDB_LOG(log, "{0}", desc_stream.str()); - return; - } - } -} - -bool ProcessWindows::CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) { - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec()); - // However, if there is no executable module, we return true since we might - // be preparing to attach. - return true; -} - -bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_THREAD); - // Add all the threads that were previously running and for which we did not - // detect a thread exited event. - int new_size = 0; - int continued_threads = 0; - int exited_threads = 0; - int new_threads = 0; - - for (ThreadSP old_thread : old_thread_list.Threads()) { - lldb::tid_t old_thread_id = old_thread->GetID(); - auto exited_thread_iter = - m_session_data->m_exited_threads.find(old_thread_id); - if (exited_thread_iter == m_session_data->m_exited_threads.end()) { - new_thread_list.AddThread(old_thread); - ++new_size; - ++continued_threads; - LLDB_LOGV(log, "Thread {0} was running and is still running.", - old_thread_id); - } else { - LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id); - ++exited_threads; - } - } - - // Also add all the threads that are new since the last time we broke into - // the debugger. - for (const auto &thread_info : m_session_data->m_new_threads) { - ThreadSP thread(new TargetThreadWindows(*this, thread_info.second)); - thread->SetID(thread_info.first); - new_thread_list.AddThread(thread); - ++new_size; - ++new_threads; - LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first); - } - - LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.", - new_threads, continued_threads, exited_threads); - - m_session_data->m_new_threads.clear(); - m_session_data->m_exited_threads.clear(); - - return new_size > 0; -} - -bool ProcessWindows::IsAlive() { - StateType state = GetPrivateState(); - switch (state) { - case eStateCrashed: - case eStateDetached: - case eStateUnloaded: - case eStateExited: - case eStateInvalid: - return false; - default: - return true; - } -} - -size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, - size_t size, Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) - return 0; - - LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size, - vm_addr); - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, - buf, size, &bytes_read)) { - // Reading from the process can fail for a number of reasons - set the - // error code and make sure that the number of bytes read is set back to 0 - // because in some scenarios the value of bytes_read returned from the API - // is garbage. - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "reading failed with error: {0}", error); - bytes_read = 0; - } - return bytes_read; -} - -size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, - size_t size, Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size, - vm_addr); - - if (!m_session_data) { - LLDB_LOG(log, "cannot write, there is no active debugger connection."); - return 0; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_written = 0; - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) - FlushInstructionCache(handle, addr, bytes_written); - else { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "writing failed with error: {0}", error); - } - return bytes_written; -} - -lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size, - permissions); - - if (!m_session_data) { - LLDB_LOG(log, "cannot allocate, there is no active debugger connection."); - error.SetErrorString( - "cannot allocate, there is no active debugger connection"); - return LLDB_INVALID_ADDRESS; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - auto protect = ConvertLldbToWinApiProtect(permissions); - auto result = VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect); - if (!result) { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "allocating failed with error: {0}", error); - return LLDB_INVALID_ADDRESS; - } - - return reinterpret_cast<addr_t>(result); -} - -Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) { - Status result; - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to deallocate bytes at address {0}", ptr); - - if (!m_session_data) { - LLDB_LOG(log, "cannot deallocate, there is no active debugger connection."); - result.SetErrorString( - "cannot deallocate, there is no active debugger connection"); - return result; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (!VirtualFreeEx(handle, reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE)) { - result.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "deallocating failed with error: {0}", result); - return result; - } - - return result; -} - -Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, - MemoryRegionInfo &info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - Status error; - llvm::sys::ScopedLock lock(m_mutex); - info.Clear(); - - if (!m_session_data) { - error.SetErrorString( - "GetMemoryRegionInfo called with no debugging session."); - LLDB_LOG(log, "error: {0}", error); - return error; - } - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { - error.SetErrorString( - "GetMemoryRegionInfo called with an invalid target process."); - LLDB_LOG(log, "error: {0}", error); - return error; - } - - LLDB_LOG(log, "getting info for address {0:x}", vm_addr); - - void *addr = reinterpret_cast<void *>(vm_addr); - MEMORY_BASIC_INFORMATION mem_info = {}; - SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); - if (result == 0) { - if (::GetLastError() == ERROR_INVALID_PARAMETER) { - // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with - // an address past the highest accessible address. We should return a - // range from the vm_addr to LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - return error; - } else { - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, - "VirtualQueryEx returned error {0} while getting memory " - "region info for address {1:x}", - error, vm_addr); - return error; - } - } - - // Protect bits are only valid for MEM_COMMIT regions. - if (mem_info.State == MEM_COMMIT) { - const bool readable = IsPageReadable(mem_info.Protect); - const bool executable = IsPageExecutable(mem_info.Protect); - const bool writable = IsPageWritable(mem_info.Protect); - info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(executable ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - } else { - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - } - - // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. - if (mem_info.State != MEM_FREE) { - info.GetRange().SetRangeBase( - reinterpret_cast<addr_t>(mem_info.AllocationBase)); - info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + - mem_info.RegionSize); - info.SetMapped(MemoryRegionInfo::eYes); - } else { - // In the unmapped case we need to return the distance to the next block of - // memory. VirtualQueryEx nearly does that except that it gives the - // distance from the start of the page containing vm_addr. - SYSTEM_INFO data; - GetSystemInfo(&data); - DWORD page_offset = vm_addr % data.dwPageSize; - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); - info.SetMapped(MemoryRegionInfo::eNo); - } - - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOGV(log, - "Memory region info for address {0}: readable={1}, " - "executable={2}, writable={3}", - vm_addr, info.GetReadable(), info.GetExecutable(), - info.GetWritable()); - return error; -} - -lldb::addr_t ProcessWindows::GetImageInfoAddress() { - Target &target = GetTarget(); - ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(&target); - if (addr.IsValid()) - return addr.GetLoadAddress(&target); - else - return LLDB_INVALID_ADDRESS; -} - -void ProcessWindows::OnExitProcess(uint32_t exit_code) { - // No need to acquire the lock since m_session_data isn't accessed. - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code); - - TargetSP target = CalculateTarget(); - if (target) { - ModuleSP executable_module = target->GetExecutableModule(); - ModuleList unloaded_modules; - unloaded_modules.Append(executable_module); - target->ModulesDidUnload(unloaded_modules, true); - } - - SetProcessExitStatus(GetID(), true, 0, exit_code); - SetPrivateState(eStateExited); - - // If the process exits before any initial stop then notify the debugger - // of the error otherwise WaitForDebuggerConnection() will be blocked. - // An example of this issue is when a process fails to load a dependent DLL. - if (m_session_data && !m_session_data->m_initial_stop_received) { - Status error(exit_code, eErrorTypeWin32); - OnDebuggerError(error, 0); - } -} - -void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { - DebuggerThreadSP debugger = m_session_data->m_debugger; - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}", - debugger->GetProcess().GetProcessId(), image_base); - - ModuleSP module = GetTarget().GetExecutableModule(); - if (!module) { - // During attach, we won't have the executable module, so find it now. - const DWORD pid = debugger->GetProcess().GetProcessId(); - const std::string file_name = GetProcessExecutableName(pid); - if (file_name.empty()) { - return; - } - - FileSpec executable_file(file_name); - FileSystem::Instance().Resolve(executable_file); - ModuleSpec module_spec(executable_file); - Status error; - module = GetTarget().GetSharedModule(module_spec, &error); - if (!module) { - return; - } - - GetTarget().SetExecutableModule(module, eLoadDependentsNo); - } - - bool load_addr_changed; - module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); - - // Add the main executable module to the list of pending module loads. We - // can't call GetTarget().ModulesDidLoad() here because we still haven't - // returned from DoLaunch() / DoAttach() yet so the target may not have set - // the process instance to `this` yet. - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wmain_thread = - debugger->GetMainThread().GetNativeThread(); - m_session_data->m_new_threads[wmain_thread.GetThreadId()] = - debugger->GetMainThread(); -} - -ExceptionResult -ProcessWindows::OnDebugException(bool first_chance, - const ExceptionRecord &record) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); - llvm::sys::ScopedLock lock(m_mutex); - - // FIXME: Without this check, occasionally when running the test suite there - // is - // an issue where m_session_data can be null. It's not clear how this could - // happen but it only surfaces while running the test suite. In order to - // properly diagnose this, we probably need to first figure allow the test - // suite to print out full lldb logs, and then add logging to the process - // plugin. - if (!m_session_data) { - LLDB_LOG(log, - "Debugger thread reported exception {0:x} at address {1:x}, " - "but there is no session.", - record.GetExceptionCode(), record.GetExceptionAddress()); - return ExceptionResult::SendToApplication; - } - - if (!first_chance) { - // Not any second chance exception is an application crash by definition. - // It may be an expression evaluation crash. - SetPrivateState(eStateStopped); - } - - ExceptionResult result = ExceptionResult::SendToApplication; - switch (record.GetExceptionCode()) { - case EXCEPTION_BREAKPOINT: - // Handle breakpoints at the first chance. - result = ExceptionResult::BreakInDebugger; - - if (!m_session_data->m_initial_stop_received) { - LLDB_LOG( - log, - "Hit loader breakpoint at address {0:x}, setting initial stop event.", - record.GetExceptionAddress()); - m_session_data->m_initial_stop_received = true; - ::SetEvent(m_session_data->m_initial_stop_event); - } else { - LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", - record.GetExceptionAddress()); - } - SetPrivateState(eStateStopped); - break; - case EXCEPTION_SINGLE_STEP: - result = ExceptionResult::BreakInDebugger; - SetPrivateState(eStateStopped); - break; - default: - LLDB_LOG(log, - "Debugger thread reported exception {0:x} at address {1:x} " - "(first_chance={2})", - record.GetExceptionCode(), record.GetExceptionAddress(), - first_chance); - // For non-breakpoints, give the application a chance to handle the - // exception first. - if (first_chance) - result = ExceptionResult::SendToApplication; - else - result = ExceptionResult::BreakInDebugger; - } - - return result; -} - -void ProcessWindows::OnCreateThread(const HostThread &new_thread) { - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); - m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; -} - -void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) { - llvm::sys::ScopedLock lock(m_mutex); - - // On a forced termination, we may get exit thread events after the session - // data has been cleaned up. - if (!m_session_data) - return; - - // A thread may have started and exited before the debugger stopped allowing a - // refresh. - // Just remove it from the new threads list in that case. - auto iter = m_session_data->m_new_threads.find(thread_id); - if (iter != m_session_data->m_new_threads.end()) - m_session_data->m_new_threads.erase(iter); - else - m_session_data->m_exited_threads.insert(thread_id); -} - -void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec, - lldb::addr_t module_addr) { - // Confusingly, there is no Target::AddSharedModule. Instead, calling - // GetSharedModule() with a new module will add it to the module list and - // return a corresponding ModuleSP. - Status error; - ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); - bool load_addr_changed = false; - module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); -} - -void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { - Address resolved_addr; - if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { - ModuleSP module = resolved_addr.GetModule(); - if (module) { - ModuleList unloaded_modules; - unloaded_modules.Append(module); - GetTarget().ModulesDidUnload(unloaded_modules, false); - } - } -} - -void ProcessWindows::OnDebugString(const std::string &string) {} - -void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) { - llvm::sys::ScopedLock lock(m_mutex); - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - - if (m_session_data->m_initial_stop_received) { - // This happened while debugging. Do we shutdown the debugging session, - // try to continue, or do something else? - LLDB_LOG(log, - "Error {0} occurred during debugging. Unexpected behavior " - "may result. {1}", - error.GetError(), error); - } else { - // If we haven't actually launched the process yet, this was an error - // launching the process. Set the internal error and signal the initial - // stop event so that the DoLaunch method wakes up and returns a failure. - m_session_data->m_launch_error = error; - ::SetEvent(m_session_data->m_initial_stop_event); - LLDB_LOG( - log, - "Error {0} occurred launching the process before the initial stop. {1}", - error.GetError(), error); - return; - } -} - -Status ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger, - HostProcess &process) { - Status result; - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | - WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "Waiting for loader breakpoint."); - - // Block this function until we receive the initial stop from the process. - if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == - WAIT_OBJECT_0) { - LLDB_LOG(log, "hit loader breakpoint, returning."); - - process = debugger->GetProcess(); - return m_session_data->m_launch_error; - } else - return Status(::GetLastError(), eErrorTypeWin32); -} - -// The Windows page protection bits are NOT independent masks that can be -// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE -// | PAGE_READ). To test for an access type, it's necessary to test for any of -// the bits that provide that access type. -bool ProcessWindows::IsPageReadable(uint32_t protect) { - return (protect & PAGE_NOACCESS) == 0; -} - -bool ProcessWindows::IsPageWritable(uint32_t protect) { - return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | - PAGE_READWRITE | PAGE_WRITECOPY)) != 0; -} - -bool ProcessWindows::IsPageExecutable(uint32_t protect) { - return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | - PAGE_EXECUTE_WRITECOPY)) != 0; -} - -} // namespace lldb_private diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.h b/source/Plugins/Process/Windows/Common/ProcessWindows.h deleted file mode 100644 index 00e384f584080..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ /dev/null @@ -1,121 +0,0 @@ -//===-- ProcessWindows.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ -#define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ - -#include "lldb/Target/Process.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-forward.h" - -#include "llvm/Support/Mutex.h" - -#include "IDebugDelegate.h" - -namespace lldb_private { - -class HostProcess; -class ProcessWindowsData; - -class ProcessWindows : public Process, public IDebugDelegate { -public: - //------------------------------------------------------------------ - // Static functions. - //------------------------------------------------------------------ - static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const FileSpec *); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Constructors and destructors - //------------------------------------------------------------------ - ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); - - ~ProcessWindows(); - - size_t GetSTDOUT(char *buf, size_t buf_size, Status &error) override; - size_t GetSTDERR(char *buf, size_t buf_size, Status &error) override; - size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override; - - // lldb_private::Process overrides - ConstString GetPluginName() override; - uint32_t GetPluginVersion() override; - - Status EnableBreakpointSite(BreakpointSite *bp_site) override; - Status DisableBreakpointSite(BreakpointSite *bp_site) override; - - Status DoDetach(bool keep_stopped) override; - Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; - Status DoAttachToProcessWithID( - lldb::pid_t pid, - const lldb_private::ProcessAttachInfo &attach_info) override; - Status DoResume() override; - Status DoDestroy() override; - Status DoHalt(bool &caused_stop) override; - - void DidLaunch() override; - void DidAttach(lldb_private::ArchSpec &arch_spec) override; - - void RefreshStateAfterStop() override; - - bool CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) override; - bool DestroyRequiresHalt() override { return false; } - bool UpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) override; - bool IsAlive() override; - - size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - Status &error) override; - size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - Status &error) override; - lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) override; - Status DoDeallocateMemory(lldb::addr_t ptr) override; - Status GetMemoryRegionInfo(lldb::addr_t vm_addr, - MemoryRegionInfo &info) override; - - lldb::addr_t GetImageInfoAddress() override; - - // IDebugDelegate overrides. - void OnExitProcess(uint32_t exit_code) override; - void OnDebuggerConnected(lldb::addr_t image_base) override; - ExceptionResult OnDebugException(bool first_chance, - const ExceptionRecord &record) override; - void OnCreateThread(const HostThread &thread) override; - void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override; - void OnLoadDll(const ModuleSpec &module_spec, - lldb::addr_t module_addr) override; - void OnUnloadDll(lldb::addr_t module_addr) override; - void OnDebugString(const std::string &string) override; - void OnDebuggerError(const Status &error, uint32_t type) override; - -private: - Status WaitForDebuggerConnection(DebuggerThreadSP debugger, - HostProcess &process); - - // These decode the page protection bits. - static bool IsPageReadable(uint32_t protect); - static bool IsPageWritable(uint32_t protect); - static bool IsPageExecutable(uint32_t protect); - - llvm::sys::Mutex m_mutex; - std::unique_ptr<ProcessWindowsData> m_session_data; -}; -} - -#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_ diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp deleted file mode 100644 index 386e9a5816c5f..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===-- ProcessWindowsLog.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessWindowsLog.h" - -using namespace lldb_private; - -static constexpr Log::Category g_categories[] = { - {{"break"}, {"log breakpoints"}, WINDOWS_LOG_BREAKPOINTS}, - {{"event"}, {"log low level debugger events"}, WINDOWS_LOG_EVENT}, - {{"exception"}, {"log exception information"}, WINDOWS_LOG_EXCEPTION}, - {{"memory"}, {"log memory reads and writes"}, WINDOWS_LOG_MEMORY}, - {{"process"}, {"log process events and activities"}, WINDOWS_LOG_PROCESS}, - {{"registers"}, {"log register read/writes"}, WINDOWS_LOG_REGISTERS}, - {{"step"}, {"log step related activities"}, WINDOWS_LOG_STEP}, - {{"thread"}, {"log thread events and activities"}, WINDOWS_LOG_THREAD}, -}; - -Log::Channel ProcessWindowsLog::g_channel(g_categories, WINDOWS_LOG_PROCESS); - -void ProcessWindowsLog::Initialize() { - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { Log::Register("windows", g_channel); }); -} - -void ProcessWindowsLog::Terminate() {} - - - - - - - - - diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h deleted file mode 100644 index b7f59c7081431..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- ProcessWindowsLog.h -------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessWindowsLog_h_ -#define liblldb_ProcessWindowsLog_h_ - -#include "lldb/Utility/Log.h" - -#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations -#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions -#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations -#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls -#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations -#define WINDOWS_LOG_STEP (1u << 5) // Log step operations -#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations -#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events - -namespace lldb_private { -class ProcessWindowsLog { - static Log::Channel g_channel; - -public: - static void Initialize(); - static void Terminate(); - - static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); } -}; -} - -#endif // liblldb_ProcessWindowsLog_h_ diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp deleted file mode 100644 index 90d43b2cf8284..0000000000000 --- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//===-- RegisterContextWindows.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-private-types.h" - -#include "ProcessWindowsLog.h" -#include "RegisterContextWindows.h" -#include "TargetThreadWindows.h" - -#include "llvm/ADT/STLExtras.h" - -using namespace lldb; -using namespace lldb_private; - -const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; - -//------------------------------------------------------------------ -// Constructors and Destructors -//------------------------------------------------------------------ -RegisterContextWindows::RegisterContextWindows(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx), m_context(), - m_context_stale(true) {} - -RegisterContextWindows::~RegisterContextWindows() {} - -void RegisterContextWindows::InvalidateAllRegisters() { - m_context_stale = true; -} - -bool RegisterContextWindows::ReadAllRegisterValues( - lldb::DataBufferSP &data_sp) { - - if (!CacheAllRegisterValues()) - return false; - - data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); - memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); - - return true; -} - -bool RegisterContextWindows::WriteAllRegisterValues( - const lldb::DataBufferSP &data_sp) { - assert(data_sp->GetByteSize() >= sizeof(m_context)); - memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); - - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - if (!::SetThreadContext( - wthread.GetHostThread().GetNativeThread().GetSystemHandle(), - &m_context)) - return false; - - return true; -} - -uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber( - lldb::RegisterKind kind, uint32_t num) { - const uint32_t num_regs = GetRegisterCount(); - - assert(kind < kNumRegisterKinds); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { - const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); - - if (reg_info->kinds[kind] == num) - return reg_idx; - } - - return LLDB_INVALID_REGNUM; -} - -//------------------------------------------------------------------ -// Subclasses can these functions if desired -//------------------------------------------------------------------ -uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() { - // Support for hardware breakpoints not yet implemented. - return 0; -} - -uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, - size_t size) { - return 0; -} - -bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) { - return false; -} - -uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() { - // Support for hardware watchpoints not yet implemented. - return 0; -} - -uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, - size_t size, bool read, - bool write) { - return 0; -} - -bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { - return false; -} - -bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } - -bool RegisterContextWindows::CacheAllRegisterValues() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); - if (!m_context_stale) - return true; - - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - memset(&m_context, 0, sizeof(m_context)); - m_context.ContextFlags = kWinContextFlags; - if (!::GetThreadContext( - wthread.GetHostThread().GetNativeThread().GetSystemHandle(), - &m_context)) { - LLDB_LOG( - log, - "GetThreadContext failed with error {0} while caching register values.", - ::GetLastError()); - return false; - } - LLDB_LOG(log, "successfully updated the register values."); - m_context_stale = false; - return true; -} diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.h b/source/Plugins/Process/Windows/Common/RegisterContextWindows.h deleted file mode 100644 index bd09295c2f238..0000000000000 --- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- RegisterContextWindows.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextWindows_H_ -#define liblldb_RegisterContextWindows_H_ - -#include "lldb/Target/RegisterContext.h" -#include "lldb/lldb-forward.h" - -namespace lldb_private { - -class Thread; - -class RegisterContextWindows : public lldb_private::RegisterContext { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextWindows(); - - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - void InvalidateAllRegisters() override; - - bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; - - bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; - - uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, - uint32_t num) override; - - //------------------------------------------------------------------ - // Subclasses can override these functions if desired - //------------------------------------------------------------------ - uint32_t NumSupportedHardwareBreakpoints() override; - - uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; - - bool ClearHardwareBreakpoint(uint32_t hw_idx) override; - - uint32_t NumSupportedHardwareWatchpoints() override; - - uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, - bool write) override; - - bool ClearHardwareWatchpoint(uint32_t hw_index) override; - - bool HardwareSingleStep(bool enable) override; - -protected: - virtual bool CacheAllRegisterValues(); - - CONTEXT m_context; - bool m_context_stale; -}; -} - -#endif // #ifndef liblldb_RegisterContextWindows_H_ diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp deleted file mode 100644 index b121dc7bf15ea..0000000000000 --- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/HostInfo.h" -#include "lldb/Host/HostNativeThreadBase.h" -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Logging.h" -#include "lldb/Utility/State.h" - -#include "Plugins/Process/Utility/UnwindLLDB.h" -#include "ProcessWindows.h" -#include "ProcessWindowsLog.h" -#include "TargetThreadWindows.h" - -#if defined(_WIN64) -#include "x64/RegisterContextWindows_x64.h" -#else -#include "x86/RegisterContextWindows_x86.h" -#endif - -using namespace lldb; -using namespace lldb_private; - -TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, - const HostThread &thread) - : Thread(process, thread.GetNativeThread().GetThreadId()), - m_thread_reg_ctx_sp(), m_host_thread(thread) {} - -TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } - -void TargetThreadWindows::RefreshStateAfterStop() { - ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); - SetState(eStateStopped); - GetRegisterContext()->InvalidateIfNeeded(false); -} - -void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} - -void TargetThreadWindows::DidStop() {} - -RegisterContextSP TargetThreadWindows::GetRegisterContext() { - if (!m_reg_context_sp) - m_reg_context_sp = CreateRegisterContextForFrame(nullptr); - - return m_reg_context_sp; -} - -RegisterContextSP -TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { - RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) { - if (!m_thread_reg_ctx_sp) { - ArchSpec arch = HostInfo::GetArchitecture(); - switch (arch.GetMachine()) { - case llvm::Triple::x86: -#if defined(_WIN64) - // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 - LLDB_LOG(log, "This is a Wow64 process, we should create a " - "RegisterContextWindows_Wow64, but we don't."); -#else - m_thread_reg_ctx_sp.reset( - new RegisterContextWindows_x86(*this, concrete_frame_idx)); -#endif - break; - case llvm::Triple::x86_64: -#if defined(_WIN64) - m_thread_reg_ctx_sp.reset( - new RegisterContextWindows_x64(*this, concrete_frame_idx)); -#else - LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit."); -#endif - default: - break; - } - } - reg_ctx_sp = m_thread_reg_ctx_sp; - } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -bool TargetThreadWindows::CalculateStopInfo() { - SetStopInfo(m_stop_info_sp); - return true; -} - -Unwind *TargetThreadWindows::GetUnwinder() { - // FIXME: Implement an unwinder based on the Windows unwinder exposed through - // DIA SDK. - if (!m_unwinder_ap) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); -} - -Status TargetThreadWindows::DoResume() { - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return Status(); - - if (resume_state == eStateStepping) { - uint32_t flags_index = - GetRegisterContext()->ConvertRegisterKindToRegisterNumber( - eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); - uint64_t flags_value = - GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); - flags_value |= 0x100; // Set the trap flag on the CPU - GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); - } - - if (resume_state == eStateStepping || resume_state == eStateRunning) { - DWORD previous_suspend_count = 0; - HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); - do { - // ResumeThread returns -1 on error, or the thread's *previous* suspend - // count on success. This means that the return value is 1 when the thread - // was restarted. Note that DWORD is an unsigned int, so we need to - // explicitly compare with -1. - previous_suspend_count = ::ResumeThread(thread_handle); - - if (previous_suspend_count == (DWORD)-1) - return Status(::GetLastError(), eErrorTypeWin32); - - } while (previous_suspend_count > 1); - } - - return Status(); -} diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h b/source/Plugins/Process/Windows/Common/TargetThreadWindows.h deleted file mode 100644 index 952c0f55b57f3..0000000000000 --- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h +++ /dev/null @@ -1,50 +0,0 @@ -//===-- TargetThreadWindows.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_Plugins_Process_Windows_TargetThreadWindows_H_ -#define liblldb_Plugins_Process_Windows_TargetThreadWindows_H_ - -//#include "ForwardDecl.h" -#include "lldb/Host/HostThread.h" -#include "lldb/Target/Thread.h" -#include "lldb/lldb-forward.h" - -#include "RegisterContextWindows.h" - -namespace lldb_private { -class ProcessWindows; -class HostThread; -class StackFrame; - -class TargetThreadWindows : public lldb_private::Thread { -public: - TargetThreadWindows(ProcessWindows &process, const HostThread &thread); - virtual ~TargetThreadWindows(); - - // lldb_private::Thread overrides - void RefreshStateAfterStop() override; - void WillResume(lldb::StateType resume_state) override; - void DidStop() override; - lldb::RegisterContextSP GetRegisterContext() override; - lldb::RegisterContextSP - CreateRegisterContextForFrame(StackFrame *frame) override; - bool CalculateStopInfo() override; - Unwind *GetUnwinder() override; - - Status DoResume(); - - HostThread GetHostThread() const { return m_host_thread; } - -private: - lldb::RegisterContextSP m_thread_reg_ctx_sp; - HostThread m_host_thread; -}; -} // namespace lldb_private - -#endif diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp deleted file mode 100644 index 584136a6e5bb4..0000000000000 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ /dev/null @@ -1,341 +0,0 @@ -//===-- RegisterContextWindows_x64.cpp --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-private-types.h" - -#include "RegisterContextWindows_x64.h" -#include "Plugins/Process/Utility/RegisterContext_x86.h" -#include "TargetThreadWindows.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" - -#include "llvm/ADT/STLExtras.h" - -using namespace lldb; -using namespace lldb_private; - -#define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase -#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary - -namespace { - -// This enum defines the layout of the global RegisterInfo array. This is -// necessary because lldb register sets are defined in terms of indices into -// the register array. As such, the order of RegisterInfos defined in global -// registers array must match the order defined here. When defining the -// register set layouts, these values can appear in an arbitrary order, and -// that determines the order that register values are displayed in a dump. -enum RegisterIndex { - eRegisterIndexRax, - eRegisterIndexRbx, - eRegisterIndexRcx, - eRegisterIndexRdx, - eRegisterIndexRdi, - eRegisterIndexRsi, - eRegisterIndexRbp, - eRegisterIndexRsp, - eRegisterIndexR8, - eRegisterIndexR9, - eRegisterIndexR10, - eRegisterIndexR11, - eRegisterIndexR12, - eRegisterIndexR13, - eRegisterIndexR14, - eRegisterIndexR15, - eRegisterIndexRip, - eRegisterIndexRflags -}; - -// Array of all register information supported by Windows x86 -RegisterInfo g_register_infos[] = { - // Macro auto defines most stuff eh_frame DWARF - // GENERIC - // GDB LLDB VALUE REGS INVALIDATE REGS - // ================================ ========================= - // ====================== ========================= - // =================== ================= ========== =============== - {DEFINE_GPR(rax, nullptr), - {dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_rax_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rbx, nullptr), - {dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_rbx_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rcx, nullptr), - {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1, - LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rdx, nullptr), - {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2, - LLDB_INVALID_REGNUM, lldb_rdx_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rdi, nullptr), - {dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_rdi_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rsi, nullptr), - {dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_rsi_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rbp, "fp"), - {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, - LLDB_INVALID_REGNUM, lldb_rbp_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rsp, "sp"), - {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, - LLDB_INVALID_REGNUM, lldb_rsp_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r8, nullptr), - {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3, - LLDB_INVALID_REGNUM, lldb_r8_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r9, nullptr), - {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4, - LLDB_INVALID_REGNUM, lldb_r9_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r10, nullptr), - {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5, - LLDB_INVALID_REGNUM, lldb_r10_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r11, nullptr), - {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6, - LLDB_INVALID_REGNUM, lldb_r11_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r12, nullptr), - {dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_r12_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r13, nullptr), - {dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_r13_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r14, nullptr), - {dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_r14_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r15, nullptr), - {dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_r15_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rip, "pc"), - {dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, - LLDB_INVALID_REGNUM, lldb_rip_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR_BIN(eflags, "flags"), - {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, - LLDB_INVALID_REGNUM, lldb_rflags_x86_64}, - nullptr, - nullptr}, -}; - -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); - -// Array of lldb register numbers used to define the set of all General Purpose -// Registers -uint32_t g_gpr_reg_indices[] = { - eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, - eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi, - eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8, - eRegisterIndexR9, eRegisterIndexR10, eRegisterIndexR11, - eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14, - eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags}; - -RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", - llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, -}; -} - -//------------------------------------------------------------------ -// Constructors and Destructors -//------------------------------------------------------------------ -RegisterContextWindows_x64::RegisterContextWindows_x64( - Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) {} - -RegisterContextWindows_x64::~RegisterContextWindows_x64() {} - -size_t RegisterContextWindows_x64::GetRegisterCount() { - return llvm::array_lengthof(g_register_infos); -} - -const RegisterInfo * -RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) { - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; -} - -size_t RegisterContextWindows_x64::GetRegisterSetCount() { - return llvm::array_lengthof(g_register_sets); -} - -const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) { - return &g_register_sets[reg_set]; -} - -bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - if (!CacheAllRegisterValues()) - return false; - - if (reg_info == nullptr) - return false; - - switch (reg_info->kinds[eRegisterKindLLDB]) { - case lldb_rax_x86_64: - reg_value.SetUInt64(m_context.Rax); - break; - case lldb_rbx_x86_64: - reg_value.SetUInt64(m_context.Rbx); - break; - case lldb_rcx_x86_64: - reg_value.SetUInt64(m_context.Rcx); - break; - case lldb_rdx_x86_64: - reg_value.SetUInt64(m_context.Rdx); - break; - case lldb_rdi_x86_64: - reg_value.SetUInt64(m_context.Rdi); - break; - case lldb_rsi_x86_64: - reg_value.SetUInt64(m_context.Rsi); - break; - case lldb_r8_x86_64: - reg_value.SetUInt64(m_context.R8); - break; - case lldb_r9_x86_64: - reg_value.SetUInt64(m_context.R9); - break; - case lldb_r10_x86_64: - reg_value.SetUInt64(m_context.R10); - break; - case lldb_r11_x86_64: - reg_value.SetUInt64(m_context.R11); - break; - case lldb_r12_x86_64: - reg_value.SetUInt64(m_context.R12); - break; - case lldb_r13_x86_64: - reg_value.SetUInt64(m_context.R13); - break; - case lldb_r14_x86_64: - reg_value.SetUInt64(m_context.R14); - break; - case lldb_r15_x86_64: - reg_value.SetUInt64(m_context.R15); - break; - case lldb_rbp_x86_64: - reg_value.SetUInt64(m_context.Rbp); - break; - case lldb_rsp_x86_64: - reg_value.SetUInt64(m_context.Rsp); - break; - case lldb_rip_x86_64: - reg_value.SetUInt64(m_context.Rip); - break; - case lldb_rflags_x86_64: - reg_value.SetUInt64(m_context.EFlags); - break; - } - return true; -} - -bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) { - // Since we cannot only write a single register value to the inferior, we - // need to make sure our cached copy of the register values are fresh. - // Otherwise when writing EAX, for example, we may also overwrite some other - // register with a stale value. - if (!CacheAllRegisterValues()) - return false; - - switch (reg_info->kinds[eRegisterKindLLDB]) { - case lldb_rax_x86_64: - m_context.Rax = reg_value.GetAsUInt64(); - break; - case lldb_rbx_x86_64: - m_context.Rbx = reg_value.GetAsUInt64(); - break; - case lldb_rcx_x86_64: - m_context.Rcx = reg_value.GetAsUInt64(); - break; - case lldb_rdx_x86_64: - m_context.Rdx = reg_value.GetAsUInt64(); - break; - case lldb_rdi_x86_64: - m_context.Rdi = reg_value.GetAsUInt64(); - break; - case lldb_rsi_x86_64: - m_context.Rsi = reg_value.GetAsUInt64(); - break; - case lldb_r8_x86_64: - m_context.R8 = reg_value.GetAsUInt64(); - break; - case lldb_r9_x86_64: - m_context.R9 = reg_value.GetAsUInt64(); - break; - case lldb_r10_x86_64: - m_context.R10 = reg_value.GetAsUInt64(); - break; - case lldb_r11_x86_64: - m_context.R11 = reg_value.GetAsUInt64(); - break; - case lldb_r12_x86_64: - m_context.R12 = reg_value.GetAsUInt64(); - break; - case lldb_r13_x86_64: - m_context.R13 = reg_value.GetAsUInt64(); - break; - case lldb_r14_x86_64: - m_context.R14 = reg_value.GetAsUInt64(); - break; - case lldb_r15_x86_64: - m_context.R15 = reg_value.GetAsUInt64(); - break; - case lldb_rbp_x86_64: - m_context.Rbp = reg_value.GetAsUInt64(); - break; - case lldb_rsp_x86_64: - m_context.Rsp = reg_value.GetAsUInt64(); - break; - case lldb_rip_x86_64: - m_context.Rip = reg_value.GetAsUInt64(); - break; - case lldb_rflags_x86_64: - m_context.EFlags = reg_value.GetAsUInt64(); - break; - } - - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext( - wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); -} diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h deleted file mode 100644 index 62cedc8fbab04..0000000000000 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- RegisterContextWindows_x64.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextWindows_x64_H_ -#define liblldb_RegisterContextWindows_x64_H_ - -#include "RegisterContextWindows.h" -#include "lldb/lldb-forward.h" - -namespace lldb_private { - -class Thread; - -class RegisterContextWindows_x64 : public RegisterContextWindows { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextWindows_x64(); - - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; - - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - - size_t GetRegisterSetCount() override; - - const RegisterSet *GetRegisterSet(size_t reg_set) override; - - bool ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - bool WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; -}; -} - -#endif // #ifndef liblldb_RegisterContextWindows_x64_H_ diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp deleted file mode 100644 index e012f9105f31a..0000000000000 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//===-- RegisterContextWindows_x86.cpp --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-private-types.h" - -#include "ProcessWindowsLog.h" -#include "RegisterContextWindows_x86.h" -#include "Plugins/Process/Utility/RegisterContext_x86.h" -#include "TargetThreadWindows.h" -#include "Plugins/Process/Utility/lldb-x86-register-enums.h" - -#include "llvm/ADT/STLExtras.h" - -using namespace lldb; -using namespace lldb_private; - -#define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase -#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary - -namespace { - -// This enum defines the layout of the global RegisterInfo array. This is -// necessary because lldb register sets are defined in terms of indices into -// the register array. As such, the order of RegisterInfos defined in global -// registers array must match the order defined here. When defining the -// register set layouts, these values can appear in an arbitrary order, and -// that determines the order that register values are displayed in a dump. -enum RegisterIndex { - eRegisterIndexEax, - eRegisterIndexEbx, - eRegisterIndexEcx, - eRegisterIndexEdx, - eRegisterIndexEdi, - eRegisterIndexEsi, - eRegisterIndexEbp, - eRegisterIndexEsp, - eRegisterIndexEip, - eRegisterIndexEflags -}; - -// Array of all register information supported by Windows x86 -RegisterInfo g_register_infos[] = { - // Macro auto defines most stuff eh_frame DWARF - // GENERIC GDB LLDB - // VALUE REGS INVALIDATE REGS - // ============================== ======================= - // =================== ========================= =================== - // ================= ========== =============== - {DEFINE_GPR(eax, nullptr), - {ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_eax_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(ebx, nullptr), - {ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_ebx_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(ecx, nullptr), - {ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_ecx_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(edx, nullptr), - {ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_edx_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(edi, nullptr), - {ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_edi_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(esi, nullptr), - {ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM, lldb_esi_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(ebp, "fp"), - {ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, - LLDB_INVALID_REGNUM, lldb_ebp_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(esp, "sp"), - {ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, - LLDB_INVALID_REGNUM, lldb_esp_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR(eip, "pc"), - {ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, - LLDB_INVALID_REGNUM, lldb_eip_i386}, - nullptr, - nullptr, - nullptr, - 0u}, - {DEFINE_GPR_BIN(eflags, "flags"), - {ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, - LLDB_INVALID_REGNUM, lldb_eflags_i386}, - nullptr, - nullptr, - nullptr, - 0u}, -}; -static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); - -// Array of lldb register numbers used to define the set of all General Purpose -// Registers -uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx, - eRegisterIndexEcx, eRegisterIndexEdx, - eRegisterIndexEdi, eRegisterIndexEsi, - eRegisterIndexEbp, eRegisterIndexEsp, - eRegisterIndexEip, eRegisterIndexEflags}; - -RegisterSet g_register_sets[] = { - {"General Purpose Registers", "gpr", - llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices}, -}; -} - -//------------------------------------------------------------------ -// Constructors and Destructors -//------------------------------------------------------------------ -RegisterContextWindows_x86::RegisterContextWindows_x86( - Thread &thread, uint32_t concrete_frame_idx) - : RegisterContextWindows(thread, concrete_frame_idx) {} - -RegisterContextWindows_x86::~RegisterContextWindows_x86() {} - -size_t RegisterContextWindows_x86::GetRegisterCount() { - return llvm::array_lengthof(g_register_infos); -} - -const RegisterInfo * -RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) { - if (reg < k_num_register_infos) - return &g_register_infos[reg]; - return NULL; -} - -size_t RegisterContextWindows_x86::GetRegisterSetCount() { - return llvm::array_lengthof(g_register_sets); -} - -const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) { - return &g_register_sets[reg_set]; -} - -bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) { - if (!CacheAllRegisterValues()) - return false; - - if (reg_info == nullptr) - return false; - - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) { - case lldb_eax_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); - case lldb_ebx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); - case lldb_ecx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); - case lldb_edx_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); - case lldb_edi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); - case lldb_esi_i386: - return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); - case lldb_ebp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); - case lldb_esp_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); - case lldb_eip_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); - case lldb_eflags_i386: - return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, - reg_value); - default: - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); - LLDB_LOG(log, "Requested unknown register {0}", reg); - break; - } - return false; -} - -bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) { - // Since we cannot only write a single register value to the inferior, we - // need to make sure our cached copy of the register values are fresh. - // Otherwise when writing EAX, for example, we may also overwrite some other - // register with a stale value. - if (!CacheAllRegisterValues()) - return false; - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); - uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - switch (reg) { - case lldb_eax_i386: - LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32()); - m_context.Eax = reg_value.GetAsUInt32(); - break; - case lldb_ebx_i386: - LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32()); - m_context.Ebx = reg_value.GetAsUInt32(); - break; - case lldb_ecx_i386: - LLDB_LOG(log, "Write value {0:x} to ECX", reg_value.GetAsUInt32()); - m_context.Ecx = reg_value.GetAsUInt32(); - break; - case lldb_edx_i386: - LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32()); - m_context.Edx = reg_value.GetAsUInt32(); - break; - case lldb_edi_i386: - LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32()); - m_context.Edi = reg_value.GetAsUInt32(); - break; - case lldb_esi_i386: - LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32()); - m_context.Esi = reg_value.GetAsUInt32(); - break; - case lldb_ebp_i386: - LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32()); - m_context.Ebp = reg_value.GetAsUInt32(); - break; - case lldb_esp_i386: - LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32()); - m_context.Esp = reg_value.GetAsUInt32(); - break; - case lldb_eip_i386: - LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32()); - m_context.Eip = reg_value.GetAsUInt32(); - break; - case lldb_eflags_i386: - LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32()); - m_context.EFlags = reg_value.GetAsUInt32(); - break; - default: - LLDB_LOG(log, "Write value {0:x} to unknown register {1}", - reg_value.GetAsUInt32(), reg); - } - - // Physically update the registers in the target process. - TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); - return ::SetThreadContext( - wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); -} - -bool RegisterContextWindows_x86::ReadRegisterHelper( - DWORD flags_required, const char *reg_name, DWORD value, - RegisterValue ®_value) const { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); - if ((m_context.ContextFlags & flags_required) != flags_required) { - LLDB_LOG(log, "Thread context doesn't have {0}", reg_name); - return false; - } - LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name); - reg_value.SetUInt32(value); - return true; -} diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h deleted file mode 100644 index aae645fdb5a3e..0000000000000 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ /dev/null @@ -1,52 +0,0 @@ -//===-- RegisterContextWindows_x86.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextWindows_x86_H_ -#define liblldb_RegisterContextWindows_x86_H_ - -#include "RegisterContextWindows.h" -#include "lldb/lldb-forward.h" - -namespace lldb_private { - -class Thread; - -class RegisterContextWindows_x86 : public RegisterContextWindows { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextWindows_x86(); - - //------------------------------------------------------------------ - // Subclasses must override these functions - //------------------------------------------------------------------ - size_t GetRegisterCount() override; - - const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; - - size_t GetRegisterSetCount() override; - - const RegisterSet *GetRegisterSet(size_t reg_set) override; - - bool ReadRegister(const RegisterInfo *reg_info, - RegisterValue ®_value) override; - - bool WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - -private: - bool ReadRegisterHelper(DWORD flags_required, const char *reg_name, - DWORD value, RegisterValue ®_value) const; -}; -} - -#endif // #ifndef liblldb_RegisterContextWindows_x86_H_ diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt deleted file mode 100644 index 9b6739824c066..0000000000000 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -add_lldb_library(lldbPluginProcessElfCore PLUGIN - ProcessElfCore.cpp - ThreadElfCore.cpp - RegisterContextPOSIXCore_arm.cpp - RegisterContextPOSIXCore_arm64.cpp - RegisterContextPOSIXCore_mips64.cpp - RegisterContextPOSIXCore_powerpc.cpp - RegisterContextPOSIXCore_ppc64le.cpp - RegisterContextPOSIXCore_s390x.cpp - RegisterContextPOSIXCore_x86_64.cpp - RegisterUtilities.cpp - - LINK_LIBS - lldbCore - lldbTarget - lldbPluginDynamicLoaderPosixDYLD - lldbPluginObjectFileELF - lldbPluginProcessUtility - LINK_COMPONENTS - BinaryFormat - Support - ) diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt deleted file mode 100644 index 4eb5291d54d5a..0000000000000 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - include_directories(${LIBXML2_INCLUDE_DIR}) -endif() - -set(LLDB_PLUGINS - lldbPluginProcessUtility - lldbPluginPlatformMacOSX -) - -if(HAVE_LIBCOMPRESSION) - set(LIBCOMPRESSION compression) -endif() - -add_lldb_library(lldbPluginProcessGDBRemote PLUGIN - GDBRemoteClientBase.cpp - GDBRemoteCommunication.cpp - GDBRemoteCommunicationClient.cpp - GDBRemoteCommunicationHistory.cpp - GDBRemoteCommunicationReplayServer.cpp - GDBRemoteCommunicationServer.cpp - GDBRemoteCommunicationServerCommon.cpp - GDBRemoteCommunicationServerLLGS.cpp - GDBRemoteCommunicationServerPlatform.cpp - GDBRemoteRegisterContext.cpp - ProcessGDBRemote.cpp - ProcessGDBRemoteLog.cpp - ThreadGDBRemote.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbDataFormatters - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - ${LLDB_PLUGINS} - ${LIBCOMPRESSION} - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/mach-core/CMakeLists.txt b/source/Plugins/Process/mach-core/CMakeLists.txt deleted file mode 100644 index e79cd82c92a67..0000000000000 --- a/source/Plugins/Process/mach-core/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_lldb_library(lldbPluginProcessMachCore PLUGIN - ProcessMachCore.cpp - ThreadMachCore.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginDynamicLoaderDarwinKernel - lldbPluginDynamicLoaderMacOSXDYLD - lldbPluginObjectFileMachO - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp deleted file mode 100644 index 08b9f08a47f67..0000000000000 --- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ /dev/null @@ -1,635 +0,0 @@ -//===-- ProcessMachCore.cpp ------------------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include <errno.h> -#include <stdlib.h> - -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/Threading.h" -#include <mutex> - -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Host/Host.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBuffer.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/State.h" - -#include "ProcessMachCore.h" -#include "Plugins/Process/Utility/StopInfoMachException.h" -#include "ThreadMachCore.h" - -// Needed for the plug-in names for the dynamic loaders. -#include "lldb/Host/SafeMachO.h" - -#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h" -#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" -#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" - -using namespace lldb; -using namespace lldb_private; - -ConstString ProcessMachCore::GetPluginNameStatic() { - static ConstString g_name("mach-o-core"); - return g_name; -} - -const char *ProcessMachCore::GetPluginDescriptionStatic() { - return "Mach-O core file debugging plug-in."; -} - -void ProcessMachCore::Terminate() { - PluginManager::UnregisterPlugin(ProcessMachCore::CreateInstance); -} - -lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp, - ListenerSP listener_sp, - const FileSpec *crash_file) { - lldb::ProcessSP process_sp; - if (crash_file) { - const size_t header_size = sizeof(llvm::MachO::mach_header); - auto data_sp = FileSystem::Instance().CreateDataBuffer( - crash_file->GetPath(), header_size, 0); - if (data_sp && data_sp->GetByteSize() == header_size) { - DataExtractor data(data_sp, lldb::eByteOrderLittle, 4); - - lldb::offset_t data_offset = 0; - llvm::MachO::mach_header mach_header; - if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) { - if (mach_header.filetype == llvm::MachO::MH_CORE) - process_sp.reset( - new ProcessMachCore(target_sp, listener_sp, *crash_file)); - } - } - } - return process_sp; -} - -bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) { - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) { - // Don't add the Target's architecture to the ModuleSpec - we may be - // working with a core file that doesn't have the correct cpusubtype in the - // header but we should still try to use it - - // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach. - ModuleSpec core_module_spec(m_core_file); - Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp, - NULL, NULL, NULL)); - - if (m_core_module_sp) { - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile) - return true; - } - } - return false; -} - -//---------------------------------------------------------------------- -// ProcessMachCore constructor -//---------------------------------------------------------------------- -ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, - ListenerSP listener_sp, - const FileSpec &core_file) - : Process(target_sp, listener_sp), m_core_aranges(), m_core_range_infos(), - m_core_module_sp(), m_core_file(core_file), - m_dyld_addr(LLDB_INVALID_ADDRESS), - m_mach_kernel_addr(LLDB_INVALID_ADDRESS), m_dyld_plugin_name() {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ProcessMachCore::~ProcessMachCore() { - Clear(); - // We need to call finalize on the process before destroying ourselves to - // make sure all of the broadcaster cleanup goes as planned. If we destruct - // this class, then Process::~Process() might have problems trying to fully - // destroy the broadcaster. - Finalize(); -} - -//---------------------------------------------------------------------- -// PluginInterface -//---------------------------------------------------------------------- -ConstString ProcessMachCore::GetPluginName() { return GetPluginNameStatic(); } - -uint32_t ProcessMachCore::GetPluginVersion() { return 1; } - -bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER | - LIBLLDB_LOG_PROCESS)); - llvm::MachO::mach_header header; - Status error; - if (DoReadMemory(addr, &header, sizeof(header), error) != sizeof(header)) - return false; - if (header.magic == llvm::MachO::MH_CIGAM || - header.magic == llvm::MachO::MH_CIGAM_64) { - header.magic = llvm::ByteSwap_32(header.magic); - header.cputype = llvm::ByteSwap_32(header.cputype); - header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); - header.filetype = llvm::ByteSwap_32(header.filetype); - header.ncmds = llvm::ByteSwap_32(header.ncmds); - header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); - header.flags = llvm::ByteSwap_32(header.flags); - } - - // TODO: swap header if needed... - // printf("0x%16.16" PRIx64 ": magic = 0x%8.8x, file_type= %u\n", vaddr, - // header.magic, header.filetype); - if (header.magic == llvm::MachO::MH_MAGIC || - header.magic == llvm::MachO::MH_MAGIC_64) { - // Check MH_EXECUTABLE to see if we can find the mach image that contains - // the shared library list. The dynamic loader (dyld) is what contains the - // list for user applications, and the mach kernel contains a global that - // has the list of kexts to load - switch (header.filetype) { - case llvm::MachO::MH_DYLINKER: - // printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr); - // Address of dyld "struct mach_header" in the core file - if (log) - log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a user " - "process dyld binary image at 0x%" PRIx64, - addr); - m_dyld_addr = addr; - return true; - - case llvm::MachO::MH_EXECUTE: - // printf("0x%16.16" PRIx64 ": file_type = MH_EXECUTE\n", vaddr); - // Check MH_EXECUTABLE file types to see if the dynamic link object flag - // is NOT set. If it isn't, then we have a mach_kernel. - if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) { - if (log) - log->Printf("ProcessMachCore::GetDynamicLoaderAddress found a mach " - "kernel binary image at 0x%" PRIx64, - addr); - // Address of the mach kernel "struct mach_header" in the core file. - m_mach_kernel_addr = addr; - return true; - } - break; - } - } - return false; -} - -//---------------------------------------------------------------------- -// Process Control -//---------------------------------------------------------------------- -Status ProcessMachCore::DoLoadCore() { - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER | - LIBLLDB_LOG_PROCESS)); - Status error; - if (!m_core_module_sp) { - error.SetErrorString("invalid core module"); - return error; - } - - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - if (core_objfile == NULL) { - error.SetErrorString("invalid core object file"); - return error; - } - - if (core_objfile->GetNumThreadContexts() == 0) { - error.SetErrorString("core file doesn't contain any LC_THREAD load " - "commands, or the LC_THREAD architecture is not " - "supported in this lldb"); - return error; - } - - SectionList *section_list = core_objfile->GetSectionList(); - if (section_list == NULL) { - error.SetErrorString("core file has no sections"); - return error; - } - - const uint32_t num_sections = section_list->GetNumSections(0); - if (num_sections == 0) { - error.SetErrorString("core file has no sections"); - return error; - } - - SetCanJIT(false); - - llvm::MachO::mach_header header; - DataExtractor data(&header, sizeof(header), - m_core_module_sp->GetArchitecture().GetByteOrder(), - m_core_module_sp->GetArchitecture().GetAddressByteSize()); - - bool ranges_are_sorted = true; - addr_t vm_addr = 0; - for (uint32_t i = 0; i < num_sections; ++i) { - Section *section = section_list->GetSectionAtIndex(i).get(); - if (section) { - lldb::addr_t section_vm_addr = section->GetFileAddress(); - FileRange file_range(section->GetFileOffset(), section->GetFileSize()); - VMRangeToFileOffset::Entry range_entry( - section_vm_addr, section->GetByteSize(), file_range); - - if (vm_addr > section_vm_addr) - ranges_are_sorted = false; - vm_addr = section->GetFileAddress(); - VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back(); - // printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - - // 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n", - // i, - // range_entry.GetRangeBase(), - // range_entry.GetRangeEnd(), - // range_entry.data.GetRangeBase(), - // range_entry.data.GetRangeEnd()); - - if (last_entry && - last_entry->GetRangeEnd() == range_entry.GetRangeBase() && - last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()) { - last_entry->SetRangeEnd(range_entry.GetRangeEnd()); - last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd()); - // puts("combine"); - } else { - m_core_aranges.Append(range_entry); - } - // Some core files don't fill in the permissions correctly. If that is - // the case assume read + execute so clients don't think the memory is - // not readable, or executable. The memory isn't writable since this - // plug-in doesn't implement DoWriteMemory. - uint32_t permissions = section->GetPermissions(); - if (permissions == 0) - permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; - m_core_range_infos.Append(VMRangeToPermissions::Entry( - section_vm_addr, section->GetByteSize(), permissions)); - } - } - if (!ranges_are_sorted) { - m_core_aranges.Sort(); - m_core_range_infos.Sort(); - } - - - bool found_main_binary_definitively = false; - - addr_t objfile_binary_addr; - UUID objfile_binary_uuid; - if (core_objfile->GetCorefileMainBinaryInfo (objfile_binary_addr, objfile_binary_uuid)) - { - if (objfile_binary_addr != LLDB_INVALID_ADDRESS) - { - m_mach_kernel_addr = objfile_binary_addr; - found_main_binary_definitively = true; - if (log) - log->Printf ("ProcessMachCore::DoLoadCore: using kernel address 0x%" PRIx64 - " from LC_NOTE 'main bin spec' load command.", m_mach_kernel_addr); - } - } - - // This checks for the presence of an LC_IDENT string in a core file; - // LC_IDENT is very obsolete and should not be used in new code, but if the - // load command is present, let's use the contents. - std::string corefile_identifier = core_objfile->GetIdentifierString(); - if (!found_main_binary_definitively && - corefile_identifier.find("Darwin Kernel") != std::string::npos) { - UUID uuid; - addr_t addr = LLDB_INVALID_ADDRESS; - if (corefile_identifier.find("UUID=") != std::string::npos) { - size_t p = corefile_identifier.find("UUID=") + strlen("UUID="); - std::string uuid_str = corefile_identifier.substr(p, 36); - uuid.SetFromStringRef(uuid_str); - } - if (corefile_identifier.find("stext=") != std::string::npos) { - size_t p = corefile_identifier.find("stext=") + strlen("stext="); - if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') { - errno = 0; - addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16); - if (errno != 0 || addr == 0) - addr = LLDB_INVALID_ADDRESS; - } - } - if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) { - m_mach_kernel_addr = addr; - found_main_binary_definitively = true; - if (log) - log->Printf( - "ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64 - " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", - addr, corefile_identifier.c_str()); - } - } - - if (!found_main_binary_definitively && - (m_dyld_addr == LLDB_INVALID_ADDRESS || - m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) { - // We need to locate the main executable in the memory ranges we have in - // the core file. We need to search for both a user-process dyld binary - // and a kernel binary in memory; we must look at all the pages in the - // binary so we don't miss one or the other. Step through all memory - // segments searching for a kernel binary and for a user process dyld -- - // we'll decide which to prefer later if both are present. - - const size_t num_core_aranges = m_core_aranges.GetSize(); - for (size_t i = 0; i < num_core_aranges; ++i) { - const VMRangeToFileOffset::Entry *entry = - m_core_aranges.GetEntryAtIndex(i); - lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); - lldb::addr_t section_vm_addr_end = entry->GetRangeEnd(); - for (lldb::addr_t section_vm_addr = section_vm_addr_start; - section_vm_addr < section_vm_addr_end; section_vm_addr += 0x1000) { - GetDynamicLoaderAddress(section_vm_addr); - } - } - } - - if (!found_main_binary_definitively && - m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { - // In the case of multiple kernel images found in the core file via - // exhaustive search, we may not pick the correct one. See if the - // DynamicLoaderDarwinKernel's search heuristics might identify the correct - // one. Most of the time, I expect the address from SearchForDarwinKernel() - // will be the same as the address we found via exhaustive search. - - if (!GetTarget().GetArchitecture().IsValid() && m_core_module_sp.get()) { - GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture()); - } - - // SearchForDarwinKernel will end up calling back into this this class in - // the GetImageInfoAddress method which will give it the - // m_mach_kernel_addr/m_dyld_addr it already has. Save that aside and set - // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so - // DynamicLoaderDarwinKernel does a real search for the kernel using its - // own heuristics. - - addr_t saved_mach_kernel_addr = m_mach_kernel_addr; - addr_t saved_user_dyld_addr = m_dyld_addr; - m_mach_kernel_addr = LLDB_INVALID_ADDRESS; - m_dyld_addr = LLDB_INVALID_ADDRESS; - - addr_t better_kernel_address = - DynamicLoaderDarwinKernel::SearchForDarwinKernel(this); - - m_mach_kernel_addr = saved_mach_kernel_addr; - m_dyld_addr = saved_user_dyld_addr; - - if (better_kernel_address != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address " - "from DynamicLoaderDarwinKernel"); - m_mach_kernel_addr = better_kernel_address; - } - } - - // If we found both a user-process dyld and a kernel binary, we need to - // decide which to prefer. - if (GetCorefilePreference() == eKernelCorefile) { - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image " - "at 0x%" PRIx64, - m_mach_kernel_addr); - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); - } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld " - "image at 0x%" PRIx64, - m_dyld_addr); - m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); - } - } else { - if (m_dyld_addr != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("ProcessMachCore::DoLoadCore: Using user process dyld " - "image at 0x%" PRIx64, - m_dyld_addr); - m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); - } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("ProcessMachCore::DoLoadCore: Using kernel corefile image " - "at 0x%" PRIx64, - m_mach_kernel_addr); - m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); - } - } - - if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) { - // For non-user process core files, the permissions on the core file - // segments are usually meaningless, they may be just "read", because we're - // dealing with kernel coredumps or early startup coredumps and the dumper - // is grabbing pages of memory without knowing what they are. If they - // aren't marked as "exeuctable", that can break the unwinder which will - // check a pc value to see if it is in an executable segment and stop the - // backtrace early if it is not ("executable" and "unknown" would both be - // fine, but "not executable" will break the unwinder). - size_t core_range_infos_size = m_core_range_infos.GetSize(); - for (size_t i = 0; i < core_range_infos_size; i++) { - VMRangeToPermissions::Entry *ent = - m_core_range_infos.GetMutableEntryAtIndex(i); - ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; - } - } - - // Even if the architecture is set in the target, we need to override it to - // match the core file which is always single arch. - ArchSpec arch(m_core_module_sp->GetArchitecture()); - if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) { - arch = Platform::GetAugmentedArchSpec(GetTarget().GetPlatform().get(), "i386"); - } - if (arch.IsValid()) - GetTarget().SetArchitecture(arch); - - return error; -} - -lldb_private::DynamicLoader *ProcessMachCore::GetDynamicLoader() { - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset(DynamicLoader::FindPlugin( - this, - m_dyld_plugin_name.IsEmpty() ? NULL : m_dyld_plugin_name.GetCString())); - return m_dyld_ap.get(); -} - -bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) { - if (old_thread_list.GetSize(false) == 0) { - // Make up the thread the first time this is called so we can setup our one - // and only core thread state. - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - - if (core_objfile) { - const uint32_t num_threads = core_objfile->GetNumThreadContexts(); - for (lldb::tid_t tid = 0; tid < num_threads; ++tid) { - ThreadSP thread_sp(new ThreadMachCore(*this, tid)); - new_thread_list.AddThread(thread_sp); - } - } - } else { - const uint32_t num_threads = old_thread_list.GetSize(false); - for (uint32_t i = 0; i < num_threads; ++i) - new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false)); - } - return new_thread_list.GetSize(false) > 0; -} - -void ProcessMachCore::RefreshStateAfterStop() { - // Let all threads recover from stopping and do any clean up based on the - // previous thread state (if any). - m_thread_list.RefreshStateAfterStop(); - // SetThreadStopInfo (m_last_stop_packet); -} - -Status ProcessMachCore::DoDestroy() { return Status(); } - -//------------------------------------------------------------------ -// Process Queries -//------------------------------------------------------------------ - -bool ProcessMachCore::IsAlive() { return true; } - -bool ProcessMachCore::WarnBeforeDetach() const { return false; } - -//------------------------------------------------------------------ -// Process Memory -//------------------------------------------------------------------ -size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size, - Status &error) { - // Don't allow the caching that lldb_private::Process::ReadMemory does since - // in core files we have it all cached our our core file anyway. - return DoReadMemory(addr, buf, size, error); -} - -size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size, - Status &error) { - ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); - size_t bytes_read = 0; - - if (core_objfile) { - //---------------------------------------------------------------------- - // Segments are not always contiguous in mach-o core files. We have core - // files that have segments like: - // Address Size File off File size - // ---------- ---------- ---------- ---------- - // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0 - // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 - // --- --- 0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000 - // 0x1d60aee8 0x00001000 --- --- 0 0x00000000 __TEXT - // - // Any if the user executes the following command: - // - // (lldb) mem read 0xf6ff0 - // - // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16 - // unless we loop through consecutive memory ranges that are contiguous in - // the address space, but not in the file data. - //---------------------------------------------------------------------- - while (bytes_read < size) { - const addr_t curr_addr = addr + bytes_read; - const VMRangeToFileOffset::Entry *core_memory_entry = - m_core_aranges.FindEntryThatContains(curr_addr); - - if (core_memory_entry) { - const addr_t offset = curr_addr - core_memory_entry->GetRangeBase(); - const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr; - const size_t bytes_to_read = - std::min(size - bytes_read, (size_t)bytes_left); - const size_t curr_bytes_read = core_objfile->CopyData( - core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, - (char *)buf + bytes_read); - if (curr_bytes_read == 0) - break; - bytes_read += curr_bytes_read; - } else { - // Only set the error if we didn't read any bytes - if (bytes_read == 0) - error.SetErrorStringWithFormat( - "core file does not contain 0x%" PRIx64, curr_addr); - break; - } - } - } - - return bytes_read; -} - -Status ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, - MemoryRegionInfo ®ion_info) { - region_info.Clear(); - const VMRangeToPermissions::Entry *permission_entry = - m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); - if (permission_entry) { - if (permission_entry->Contains(load_addr)) { - region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); - const Flags permissions(permission_entry->data); - region_info.SetReadable(permissions.Test(ePermissionsReadable) - ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetWritable(permissions.Test(ePermissionsWritable) - ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetExecutable(permissions.Test(ePermissionsExecutable) - ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eYes); - } else if (load_addr < permission_entry->GetRangeBase()) { - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - } - return Status(); - } - - region_info.GetRange().SetRangeBase(load_addr); - region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - region_info.SetReadable(MemoryRegionInfo::eNo); - region_info.SetWritable(MemoryRegionInfo::eNo); - region_info.SetExecutable(MemoryRegionInfo::eNo); - region_info.SetMapped(MemoryRegionInfo::eNo); - return Status(); -} - -void ProcessMachCore::Clear() { m_thread_list.Clear(); } - -void ProcessMachCore::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); - }); -} - -addr_t ProcessMachCore::GetImageInfoAddress() { - // If we found both a user-process dyld and a kernel binary, we need to - // decide which to prefer. - if (GetCorefilePreference() == eKernelCorefile) { - if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { - return m_mach_kernel_addr; - } - return m_dyld_addr; - } else { - if (m_dyld_addr != LLDB_INVALID_ADDRESS) { - return m_dyld_addr; - } - return m_mach_kernel_addr; - } -} - -lldb_private::ObjectFile *ProcessMachCore::GetCoreObjectFile() { - return m_core_module_sp->GetObjectFile(); -} diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.h b/source/Plugins/Process/mach-core/ProcessMachCore.h deleted file mode 100644 index 0c6fc693a50c5..0000000000000 --- a/source/Plugins/Process/mach-core/ProcessMachCore.h +++ /dev/null @@ -1,149 +0,0 @@ -//===-- ProcessMachCore.h ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessMachCore_h_ -#define liblldb_ProcessMachCore_h_ - -#include <list> -#include <vector> - -#include "lldb/Target/Process.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Status.h" - -class ThreadKDP; - -class ProcessMachCore : public lldb_private::Process { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - ProcessMachCore(lldb::TargetSP target_sp, lldb::ListenerSP listener, - const lldb_private::FileSpec &core_file); - - ~ProcessMachCore() override; - - static lldb::ProcessSP - CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, - const lldb_private::FileSpec *crash_file_path); - - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - //------------------------------------------------------------------ - // Check if a given Process - //------------------------------------------------------------------ - bool CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) override; - - //------------------------------------------------------------------ - // Creating a new process, or attaching to an existing one - //------------------------------------------------------------------ - lldb_private::Status DoLoadCore() override; - - lldb_private::DynamicLoader *GetDynamicLoader() override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - - //------------------------------------------------------------------ - // Process Control - //------------------------------------------------------------------ - lldb_private::Status DoDestroy() override; - - void RefreshStateAfterStop() override; - - //------------------------------------------------------------------ - // Process Queries - //------------------------------------------------------------------ - bool IsAlive() override; - - bool WarnBeforeDetach() const override; - - //------------------------------------------------------------------ - // Process Memory - //------------------------------------------------------------------ - size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size, - lldb_private::Status &error) override; - - size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, - lldb_private::Status &error) override; - - lldb_private::Status - GetMemoryRegionInfo(lldb::addr_t load_addr, - lldb_private::MemoryRegionInfo ®ion_info) override; - - lldb::addr_t GetImageInfoAddress() override; - -protected: - friend class ThreadMachCore; - - void Clear(); - - bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list) override; - - lldb_private::ObjectFile *GetCoreObjectFile(); - -private: - bool GetDynamicLoaderAddress(lldb::addr_t addr); - - typedef enum CorefilePreference { - eUserProcessCorefile, - eKernelCorefile - } CorefilePreferences; - - //------------------------------------------------------------------ - /// If a core file can be interpreted multiple ways, this establishes - /// which style wins. - /// - /// If a core file contains both a kernel binary and a user-process - /// dynamic loader, lldb needs to pick one over the other. This could - /// be a kernel corefile that happens to have a copy of dyld in its - /// memory. Or it could be a user process coredump of lldb while doing - /// kernel debugging - so a copy of the kernel is in its heap. This - /// should become a setting so it can be over-ridden when necessary. - //------------------------------------------------------------------ - CorefilePreference GetCorefilePreference() { - // For now, if both user process and kernel binaries a present, - // assume this is a kernel coredump which has a copy of a user - // process dyld in one of its pages. - return eKernelCorefile; - } - - //------------------------------------------------------------------ - // For ProcessMachCore only - //------------------------------------------------------------------ - typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange> - VMRangeToFileOffset; - typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> - VMRangeToPermissions; - - VMRangeToFileOffset m_core_aranges; - VMRangeToPermissions m_core_range_infos; - lldb::ModuleSP m_core_module_sp; - lldb_private::FileSpec m_core_file; - lldb::addr_t m_dyld_addr; - lldb::addr_t m_mach_kernel_addr; - lldb_private::ConstString m_dyld_plugin_name; - - DISALLOW_COPY_AND_ASSIGN(ProcessMachCore); -}; - -#endif // liblldb_ProcessMachCore_h_ diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp deleted file mode 100644 index 16edd28f1a132..0000000000000 --- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//===-- ThreadMachCore.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ThreadMachCore.h" - -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Unwind.h" -#include "lldb/Utility/ArchSpec.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/State.h" -#include "lldb/Utility/StreamString.h" - -#include "ProcessMachCore.h" -//#include "RegisterContextKDP_arm.h" -//#include "RegisterContextKDP_i386.h" -//#include "RegisterContextKDP_x86_64.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Thread Registers -//---------------------------------------------------------------------- - -ThreadMachCore::ThreadMachCore(Process &process, lldb::tid_t tid) - : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), - m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), m_thread_reg_ctx_sp() {} - -ThreadMachCore::~ThreadMachCore() { DestroyThread(); } - -const char *ThreadMachCore::GetName() { - if (m_thread_name.empty()) - return nullptr; - return m_thread_name.c_str(); -} - -void ThreadMachCore::RefreshStateAfterStop() { - // Invalidate all registers in our register context. We don't set "force" to - // true because the stop reply packet might have had some register values - // that were expedited and these will already be copied into the register - // context by the time this function gets called. The KDPRegisterContext - // class has been made smart enough to detect when it needs to invalidate - // which registers are valid by putting hooks in the register read and - // register supply functions where they check the process stop ID and do the - // right thing. - const bool force = false; - GetRegisterContext()->InvalidateIfNeeded(force); -} - -bool ThreadMachCore::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } - -lldb::RegisterContextSP ThreadMachCore::GetRegisterContext() { - if (!m_reg_context_sp) - m_reg_context_sp = CreateRegisterContextForFrame(nullptr); - return m_reg_context_sp; -} - -lldb::RegisterContextSP -ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) { - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) { - if (!m_thread_reg_ctx_sp) { - ProcessSP process_sp(GetProcess()); - - ObjectFile *core_objfile = - static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile(); - if (core_objfile) - m_thread_reg_ctx_sp = - core_objfile->GetThreadContextAtIndex(GetID(), *this); - } - reg_ctx_sp = m_thread_reg_ctx_sp; - } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); - } - return reg_ctx_sp; -} - -bool ThreadMachCore::CalculateStopInfo() { - ProcessSP process_sp(GetProcess()); - if (process_sp) { - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, SIGSTOP)); - return true; - } - return false; -} diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.h b/source/Plugins/Process/mach-core/ThreadMachCore.h deleted file mode 100644 index 696ba7294e4aa..0000000000000 --- a/source/Plugins/Process/mach-core/ThreadMachCore.h +++ /dev/null @@ -1,70 +0,0 @@ -//===-- ThreadMachCore.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ThreadMachCore_h_ -#define liblldb_ThreadMachCore_h_ - -#include <string> - -#include "lldb/Target/Thread.h" - -class ProcessMachCore; - -class ThreadMachCore : public lldb_private::Thread { -public: - ThreadMachCore(lldb_private::Process &process, lldb::tid_t tid); - - ~ThreadMachCore() override; - - void RefreshStateAfterStop() override; - - const char *GetName() override; - - lldb::RegisterContextSP GetRegisterContext() override; - - lldb::RegisterContextSP - CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; - - static bool ThreadIDIsValid(lldb::tid_t thread); - - bool ShouldStop(bool &step_more); - - const char *GetBasicInfoAsString(); - - void SetName(const char *name) override { - if (name && name[0]) - m_thread_name.assign(name); - else - m_thread_name.clear(); - } - - lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; } - - void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) { - m_thread_dispatch_qaddr = thread_dispatch_qaddr; - } - -protected: - friend class ProcessMachCore; - - //------------------------------------------------------------------ - // Member variables. - //------------------------------------------------------------------ - std::string m_thread_name; - std::string m_dispatch_queue_name; - lldb::addr_t m_thread_dispatch_qaddr; - lldb::RegisterContextSP m_thread_reg_ctx_sp; - - //------------------------------------------------------------------ - // Protected member functions. - //------------------------------------------------------------------ - bool CalculateStopInfo() override; -}; - -#endif // liblldb_ThreadMachCore_h_ diff --git a/source/Plugins/Process/minidump/CMakeLists.txt b/source/Plugins/Process/minidump/CMakeLists.txt deleted file mode 100644 index 4126a7ea991c2..0000000000000 --- a/source/Plugins/Process/minidump/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -add_lldb_library(lldbPluginProcessMinidump PLUGIN - MinidumpTypes.cpp - MinidumpParser.cpp - RegisterContextMinidump_ARM.cpp - RegisterContextMinidump_ARM64.cpp - RegisterContextMinidump_x86_32.cpp - RegisterContextMinidump_x86_64.cpp - ProcessMinidump.cpp - ThreadMinidump.cpp - - LINK_LIBS - lldbCore - lldbTarget - lldbUtility - lldbPluginProcessUtility - lldbPluginProcessElfCore - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/ScriptInterpreter/CMakeLists.txt b/source/Plugins/ScriptInterpreter/CMakeLists.txt deleted file mode 100644 index 5d8642eb07e67..0000000000000 --- a/source/Plugins/ScriptInterpreter/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_subdirectory(None) -if (NOT LLDB_DISABLE_PYTHON) - add_subdirectory(Python) -endif() diff --git a/source/Plugins/ScriptInterpreter/None/CMakeLists.txt b/source/Plugins/ScriptInterpreter/None/CMakeLists.txt deleted file mode 100644 index 7e7dd5896f7c8..0000000000000 --- a/source/Plugins/ScriptInterpreter/None/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_lldb_library(lldbPluginScriptInterpreterNone PLUGIN - ScriptInterpreterNone.cpp - - LINK_LIBS - lldbCore - lldbInterpreter - )
\ No newline at end of file diff --git a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt deleted file mode 100644 index 56eacc941d64b..0000000000000 --- a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - # Call a python script to gather the arch-specific libdir for - # modules like the lldb module. - execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../../../scripts/get_relative_lib_dir.py - RESULT_VARIABLE get_libdir_status - OUTPUT_VARIABLE relative_libdir - ) - if (get_libdir_status EQUAL 0) - add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${relative_libdir}") - endif() -endif() - -add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN - PythonDataObjects.cpp - PythonExceptionState.cpp - ScriptInterpreterPython.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbDataFormatters - lldbHost - lldbInterpreter - lldbTarget - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/StructuredData/CMakeLists.txt b/source/Plugins/StructuredData/CMakeLists.txt deleted file mode 100644 index 40d64558482db..0000000000000 --- a/source/Plugins/StructuredData/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(DarwinLog) - diff --git a/source/Plugins/StructuredData/DarwinLog/CMakeLists.txt b/source/Plugins/StructuredData/DarwinLog/CMakeLists.txt deleted file mode 100644 index 4df391276c002..0000000000000 --- a/source/Plugins/StructuredData/DarwinLog/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_lldb_library(lldbPluginStructuredDataDarwinLog PLUGIN - StructuredDataDarwinLog.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbHost - lldbInterpreter - lldbTarget - ) diff --git a/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt b/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt deleted file mode 100644 index e93d0618a0e48..0000000000000 --- a/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -add_lldb_library(lldbPluginSymbolFileBreakpad PLUGIN - SymbolFileBreakpad.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - lldbUtility - lldbPluginObjectFileBreakpad - LINK_COMPONENTS - Support - ) diff --git a/source/Plugins/SymbolFile/CMakeLists.txt b/source/Plugins/SymbolFile/CMakeLists.txt deleted file mode 100644 index ad1c92bd84698..0000000000000 --- a/source/Plugins/SymbolFile/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_subdirectory(Breakpad) -add_subdirectory(DWARF) -add_subdirectory(Symtab) -add_subdirectory(NativePDB) -add_subdirectory(PDB) diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt deleted file mode 100644 index 0e47ee34fe51b..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ /dev/null @@ -1,55 +0,0 @@ -add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN - AppleDWARFIndex.cpp - DebugNamesDWARFIndex.cpp - DIERef.cpp - DWARFAbbreviationDeclaration.cpp - DWARFASTParserClang.cpp - DWARFAttribute.cpp - DWARFBaseDIE.cpp - DWARFCompileUnit.cpp - DWARFDataExtractor.cpp - DWARFDebugAbbrev.cpp - DWARFDebugAranges.cpp - DWARFDebugArangeSet.cpp - DWARFDebugInfo.cpp - DWARFDebugInfoEntry.cpp - DWARFDebugLine.cpp - DWARFDebugMacro.cpp - DWARFDebugMacinfo.cpp - DWARFDebugMacinfoEntry.cpp - DWARFDebugRanges.cpp - DWARFDeclContext.cpp - DWARFDefines.cpp - DWARFDIE.cpp - DWARFDIECollection.cpp - DWARFFormValue.cpp - DWARFIndex.cpp - DWARFUnit.cpp - HashedNameToDIE.cpp - LogChannelDWARF.cpp - ManualDWARFIndex.cpp - NameToDIE.cpp - SymbolFileDWARF.cpp - SymbolFileDWARFDwo.cpp - SymbolFileDWARFDwoDwp.cpp - SymbolFileDWARFDwp.cpp - SymbolFileDWARFDebugMap.cpp - UniqueDWARFASTType.cpp - - LINK_LIBS - clangAST - clangBasic - lldbCore - lldbExpression - lldbHost - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - lldbPluginObjCLanguage - lldbPluginCPlusPlusLanguage - lldbPluginExpressionParserClang - LINK_COMPONENTS - DebugInfoDWARF - Support - ) diff --git a/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt deleted file mode 100644 index da2d7fe8108aa..0000000000000 --- a/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN - CompileUnitIndex.cpp - DWARFLocationExpression.cpp - PdbAstBuilder.cpp - PdbIndex.cpp - PdbSymUid.cpp - PdbUtil.cpp - SymbolFileNativePDB.cpp - UdtRecordCompleter.cpp - - LINK_LIBS - clangAST - clangLex - lldbCore - lldbSymbol - lldbUtility - LINK_COMPONENTS - DebugInfoCodeView - DebugInfoPDB - Support - ) diff --git a/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/source/Plugins/SymbolFile/PDB/CMakeLists.txt deleted file mode 100644 index 19698a7187f71..0000000000000 --- a/source/Plugins/SymbolFile/PDB/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -add_lldb_library(lldbPluginSymbolFilePDB PLUGIN - PDBASTParser.cpp - PDBLocationToDWARFExpression.cpp - SymbolFilePDB.cpp - - LINK_LIBS - clangAST - clangLex - lldbCore - lldbSymbol - lldbUtility - lldbPluginSymbolFileNativePDB - LINK_COMPONENTS - DebugInfoPDB - Support - ) diff --git a/source/Plugins/SymbolFile/Symtab/CMakeLists.txt b/source/Plugins/SymbolFile/Symtab/CMakeLists.txt deleted file mode 100644 index a2e19bd283f19..0000000000000 --- a/source/Plugins/SymbolFile/Symtab/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_lldb_library(lldbPluginSymbolFileSymtab PLUGIN - SymbolFileSymtab.cpp - - LINK_LIBS - lldbCore - lldbSymbol - ) diff --git a/source/Plugins/SymbolVendor/CMakeLists.txt b/source/Plugins/SymbolVendor/CMakeLists.txt deleted file mode 100644 index 94862d5887271..0000000000000 --- a/source/Plugins/SymbolVendor/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX) -endif() - -add_subdirectory(ELF) diff --git a/source/Plugins/SymbolVendor/ELF/CMakeLists.txt b/source/Plugins/SymbolVendor/ELF/CMakeLists.txt deleted file mode 100644 index e742fac931291..0000000000000 --- a/source/Plugins/SymbolVendor/ELF/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_lldb_library(lldbPluginSymbolVendorELF PLUGIN - SymbolVendorELF.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - ) diff --git a/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt b/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt deleted file mode 100644 index bbcdff9705aff..0000000000000 --- a/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -include_directories(${LIBXML2_INCLUDE_DIR}) - -add_lldb_library(lldbPluginSymbolVendorMacOSX PLUGIN - SymbolVendorMacOSX.cpp - - LINK_LIBS - lldbCore - lldbHost - lldbSymbol - ) diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp deleted file mode 100644 index 169eed817566b..0000000000000 --- a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp +++ /dev/null @@ -1,321 +0,0 @@ -//===-- SymbolVendorMacOSX.cpp ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "SymbolVendorMacOSX.h" - -#include <string.h> - -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/Symbols.h" -#include "lldb/Host/XML.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/Utility/Timer.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// SymbolVendorMacOSX constructor -//---------------------------------------------------------------------- -SymbolVendorMacOSX::SymbolVendorMacOSX(const lldb::ModuleSP &module_sp) - : SymbolVendor(module_sp) {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -SymbolVendorMacOSX::~SymbolVendorMacOSX() {} - -static bool UUIDsMatch(Module *module, ObjectFile *ofile, - lldb_private::Stream *feedback_strm) { - if (module && ofile) { - // Make sure the UUIDs match - lldb_private::UUID dsym_uuid; - - if (!ofile->GetUUID(&dsym_uuid)) { - if (feedback_strm) { - feedback_strm->PutCString( - "warning: failed to get the uuid for object file: '"); - ofile->GetFileSpec().Dump(feedback_strm); - feedback_strm->PutCString("\n"); - } - return false; - } - - if (dsym_uuid == module->GetUUID()) - return true; - - // Emit some warning messages since the UUIDs do not match! - if (feedback_strm) { - feedback_strm->PutCString( - "warning: UUID mismatch detected between modules:\n "); - module->GetUUID().Dump(feedback_strm); - feedback_strm->PutChar(' '); - module->GetFileSpec().Dump(feedback_strm); - feedback_strm->PutCString("\n "); - dsym_uuid.Dump(feedback_strm); - feedback_strm->PutChar(' '); - ofile->GetFileSpec().Dump(feedback_strm); - feedback_strm->EOL(); - } - } - return false; -} - -void SymbolVendorMacOSX::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void SymbolVendorMacOSX::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString SymbolVendorMacOSX::GetPluginNameStatic() { - static ConstString g_name("macosx"); - return g_name; -} - -const char *SymbolVendorMacOSX::GetPluginDescriptionStatic() { - return "Symbol vendor for MacOSX that looks for dSYM files that match " - "executables."; -} - -//---------------------------------------------------------------------- -// CreateInstance -// -// Platforms can register a callback to use when creating symbol vendors to -// allow for complex debug information file setups, and to also allow for -// finding separate debug information files. -//---------------------------------------------------------------------- -SymbolVendor * -SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp, - lldb_private::Stream *feedback_strm) { - if (!module_sp) - return NULL; - - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (!obj_file) - return NULL; - - static ConstString obj_file_macho("mach-o"); - ConstString obj_name = obj_file->GetPluginName(); - if (obj_name != obj_file_macho) - return NULL; - - static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); - Timer scoped_timer(func_cat, - "SymbolVendorMacOSX::CreateInstance (module = %s)", - module_sp->GetFileSpec().GetPath().c_str()); - SymbolVendorMacOSX *symbol_vendor = new SymbolVendorMacOSX(module_sp); - if (symbol_vendor) { - char path[PATH_MAX]; - path[0] = '\0'; - - // Try and locate the dSYM file on Mac OS X - static Timer::Category func_cat2( - "SymbolVendorMacOSX::CreateInstance() locate dSYM"); - Timer scoped_timer2( - func_cat2, - "SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM", - module_sp->GetFileSpec().GetPath().c_str()); - - // First check to see if the module has a symbol file in mind already. If - // it does, then we MUST use that. - FileSpec dsym_fspec(module_sp->GetSymbolFileFileSpec()); - - ObjectFileSP dsym_objfile_sp; - if (!dsym_fspec) { - // No symbol file was specified in the module, lets try and find one - // ourselves. - FileSpec file_spec = obj_file->GetFileSpec(); - if (!file_spec) - file_spec = module_sp->GetFileSpec(); - - ModuleSpec module_spec(file_spec, module_sp->GetArchitecture()); - module_spec.GetUUID() = module_sp->GetUUID(); - dsym_fspec = Symbols::LocateExecutableSymbolFile(module_spec); - if (module_spec.GetSourceMappingList().GetSize()) - module_sp->GetSourceMappingList().Append( - module_spec.GetSourceMappingList(), true); - } - - if (dsym_fspec) { - DataBufferSP dsym_file_data_sp; - lldb::offset_t dsym_file_data_offset = 0; - dsym_objfile_sp = - ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, - FileSystem::Instance().GetByteSize(dsym_fspec), - dsym_file_data_sp, dsym_file_data_offset); - if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) { - // We need a XML parser if we hope to parse a plist... - if (XMLDocument::XMLEnabled()) { - char dsym_path[PATH_MAX]; - if (module_sp->GetSourceMappingList().IsEmpty() && - dsym_fspec.GetPath(dsym_path, sizeof(dsym_path))) { - lldb_private::UUID dsym_uuid; - if (dsym_objfile_sp->GetUUID(&dsym_uuid)) { - std::string uuid_str = dsym_uuid.GetAsString(); - if (!uuid_str.empty()) { - char *resources = strstr(dsym_path, "/Contents/Resources/"); - if (resources) { - char dsym_uuid_plist_path[PATH_MAX]; - resources[strlen("/Contents/Resources/")] = '\0'; - snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path), - "%s%s.plist", dsym_path, uuid_str.c_str()); - FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path); - if (FileSystem::Instance().Exists(dsym_uuid_plist_spec)) { - ApplePropertyList plist(dsym_uuid_plist_path); - if (plist) { - std::string DBGBuildSourcePath; - std::string DBGSourcePath; - - // DBGSourcePathRemapping is a dictionary in the plist - // with keys which are DBGBuildSourcePath file paths and - // values which are DBGSourcePath file paths - - StructuredData::ObjectSP plist_sp = - plist.GetStructuredData(); - if (plist_sp.get() && plist_sp->GetAsDictionary() && - plist_sp->GetAsDictionary()->HasKey( - "DBGSourcePathRemapping") && - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGSourcePathRemapping") - ->GetAsDictionary()) { - - // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping. - // If DBGVersion 2, strip last two components of path remappings from - // entries to fix an issue with a specific set of - // DBGSourcePathRemapping entries that lldb worked - // with. - // If DBGVersion 3, trust & use the source path remappings as-is. - // - - bool new_style_source_remapping_dictionary = false; - bool do_truncate_remapping_names = false; - std::string original_DBGSourcePath_value = - DBGSourcePath; - if (plist_sp->GetAsDictionary()->HasKey("DBGVersion")) { - std::string version_string = - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGVersion") - ->GetStringValue(""); - if (!version_string.empty() && - isdigit(version_string[0])) { - int version_number = atoi(version_string.c_str()); - if (version_number > 1) { - new_style_source_remapping_dictionary = true; - } - if (version_number == 2) { - do_truncate_remapping_names = true; - } - } - } - - StructuredData::Dictionary *remappings_dict = - plist_sp->GetAsDictionary() - ->GetValueForKey("DBGSourcePathRemapping") - ->GetAsDictionary(); - remappings_dict->ForEach( - [&module_sp, new_style_source_remapping_dictionary, - original_DBGSourcePath_value, do_truncate_remapping_names]( - ConstString key, - StructuredData::Object *object) -> bool { - if (object && object->GetAsString()) { - - // key is DBGBuildSourcePath - // object is DBGSourcePath - std::string DBGSourcePath = - object->GetStringValue(); - if (!new_style_source_remapping_dictionary && - !original_DBGSourcePath_value.empty()) { - DBGSourcePath = original_DBGSourcePath_value; - } - if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path( - DBGSourcePath.c_str()); - FileSystem::Instance().Resolve( - resolved_source_path); - DBGSourcePath = - resolved_source_path.GetPath(); - } - module_sp->GetSourceMappingList().Append( - key, ConstString(DBGSourcePath), true); - // With version 2 of DBGSourcePathRemapping, we - // can chop off the last two filename parts - // from the source remapping and get a more - // general source remapping that still works. - // Add this as another option in addition to - // the full source path remap. - if (do_truncate_remapping_names) { - FileSpec build_path(key.AsCString()); - FileSpec source_path(DBGSourcePath.c_str()); - build_path.RemoveLastPathComponent(); - build_path.RemoveLastPathComponent(); - source_path.RemoveLastPathComponent(); - source_path.RemoveLastPathComponent(); - module_sp->GetSourceMappingList().Append( - ConstString(build_path.GetPath().c_str()), - ConstString(source_path.GetPath().c_str()), true); - } - } - return true; - }); - } - - // If we have a DBGBuildSourcePath + DBGSourcePath pair, - // append those to the source path remappings. - - plist.GetValueAsString("DBGBuildSourcePath", - DBGBuildSourcePath); - plist.GetValueAsString("DBGSourcePath", DBGSourcePath); - if (!DBGBuildSourcePath.empty() && - !DBGSourcePath.empty()) { - if (DBGSourcePath[0] == '~') { - FileSpec resolved_source_path(DBGSourcePath.c_str()); - FileSystem::Instance().Resolve(resolved_source_path); - DBGSourcePath = resolved_source_path.GetPath(); - } - module_sp->GetSourceMappingList().Append( - ConstString(DBGBuildSourcePath), - ConstString(DBGSourcePath), true); - } - } - } - } - } - } - } - } - - symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp); - return symbol_vendor; - } - } - - // Just create our symbol vendor using the current objfile as this is - // either an executable with no dSYM (that we could locate), an executable - // with a dSYM that has a UUID that doesn't match. - symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this()); - } - return symbol_vendor; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -ConstString SymbolVendorMacOSX::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t SymbolVendorMacOSX::GetPluginVersion() { return 1; } diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h deleted file mode 100644 index 53b5291af0314..0000000000000 --- a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- SymbolVendorMacOSX.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_SymbolVendorMacOSX_h_ -#define liblldb_SymbolVendorMacOSX_h_ - -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/lldb-private.h" - -class SymbolVendorMacOSX : public lldb_private::SymbolVendor { -public: - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::SymbolVendor * - CreateInstance(const lldb::ModuleSP &module_sp, - lldb_private::Stream *feedback_strm); - - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - SymbolVendorMacOSX(const lldb::ModuleSP &module_sp); - - virtual ~SymbolVendorMacOSX(); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual lldb_private::ConstString GetPluginName(); - - virtual uint32_t GetPluginVersion(); - -private: - DISALLOW_COPY_AND_ASSIGN(SymbolVendorMacOSX); -}; - -#endif // liblldb_SymbolVendorMacOSX_h_ diff --git a/source/Plugins/SystemRuntime/CMakeLists.txt b/source/Plugins/SystemRuntime/CMakeLists.txt deleted file mode 100644 index 0955a9eb74c2d..0000000000000 --- a/source/Plugins/SystemRuntime/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(MacOSX) diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp deleted file mode 100644 index 43e401330c5c5..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ /dev/null @@ -1,398 +0,0 @@ -//===-- AppleGetItemInfoHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetItemInfoHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetItemInfoHandler::g_get_item_info_function_name = - "__lldb_backtrace_recording_get_item_info"; -const char *AppleGetItemInfoHandler::g_get_item_info_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern uint64_t __introspection_dispatch_queue_item_get_info (introspection_dispatch_item_info_ref item_info_ref, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_item_info_return_values \n\ - { \n\ - uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_item_info \n\ - (struct get_item_info_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t /* introspection_dispatch_item_info_ref item_info_ref */ item, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_item_info with args return_buffer == %p, debug == %d, item == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, item, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - __introspection_dispatch_queue_item_get_info ((void*) item, \n\ - (void**)&return_buffer->item_info_buffer_ptr, \n\ - &return_buffer->item_info_buffer_size); \n\ -} \n\ -} \n\ -"; - -AppleGetItemInfoHandler::AppleGetItemInfoHandler(Process *process) - : m_process(process), m_get_item_info_impl_code(), - m_get_item_info_function_mutex(), - m_get_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_item_info_retbuffer_mutex() {} - -AppleGetItemInfoHandler::~AppleGetItemInfoHandler() {} - -void AppleGetItemInfoHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_item_info_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_item_info_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_item_info() function (from the -// source above in g_get_item_info_function_code) if we don't find that -// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g. -// this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_item_info into the inferior -// process if needed. -// -// Write the get_item_info_arglist into the inferior's memory space to prepare -// for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction( - Thread &thread, ValueList &get_item_info_arglist) { - ExecutionContext exe_ctx(thread.shared_from_this()); - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_item_info_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_item_info_function_mutex); - - // First stage is to make the UtilityFunction to hold our injected - // function: - - if (!m_get_item_info_impl_code.get()) { - if (g_get_item_info_function_code != NULL) { - Status error; - m_get_item_info_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_item_info_function_code, eLanguageTypeObjC, - g_get_item_info_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get utility function: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install get-item-info introspection."); - diagnostics.Dump(log); - } - m_get_item_info_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No get-item-info introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Next make the runner function for our implementation utility function. - Status error; - - TypeSystem *type_system = - thread.GetProcess()->GetTarget().GetScratchTypeSystemForLanguage( - nullptr, eLanguageTypeC); - CompilerType get_item_info_return_type = - type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); - - get_item_info_caller = m_get_item_info_impl_code->MakeFunctionCaller( - get_item_info_return_type, get_item_info_arglist, - thread.shared_from_this(), error); - if (error.Fail() || get_item_info_caller == nullptr) { - if (log) - log->Printf("Error Inserting get-item-info function: \"%s\".", - error.AsCString()); - return args_addr; - } - } else { - // If it's already made, then we can just retrieve the caller: - get_item_info_caller = m_get_item_info_impl_code->GetFunctionCaller(); - if (!get_item_info_caller) { - if (log) - log->Printf("Failed to get get-item-info introspection caller."); - m_get_item_info_impl_code.reset(); - return args_addr; - } - } - } - - diagnostics.Clear(); - - // Now write down the argument values for this particular call. This looks - // like it might be a race condition if other threads were calling into here, - // but actually it isn't because we allocate a new args structure for this - // call by passing args_addr = LLDB_INVALID_ADDRESS... - - if (!get_item_info_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_item_info_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-item-info function arguments."); - diagnostics.Dump(log); - } - - return args_addr; - } - - return args_addr; -} - -AppleGetItemInfoHandler::GetItemInfoReturnInfo -AppleGetItemInfoHandler::GetItemInfo(Thread &thread, uint64_t item, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetItemInfoReturnInfo return_value; - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.item_buffer_size = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_item_info_return_values - // { - // uint64_t item_info_buffer_ptr; /* the address of the items buffer - // from libBacktraceRecording */ - // uint64_t item_info_buffer_size; /* the size of the items buffer from - // libBacktraceRecording */ - // }; - // - // void __lldb_backtrace_recording_get_item_info - // (struct - // get_item_info_return_values - // *return_buffer, - // int debug, - // uint64_t item, - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value item_value; - item_value.SetValueType(Value::eValueTypeScalar); - item_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_item_info_retbuffer_mutex); - if (m_get_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_item_info_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_item_info_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - item_value.GetScalar() = item; - argument_values.PushValue(item_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetItemInfoFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (!m_get_item_info_impl_code) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_queue_item_get_info"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - FunctionCaller *func_caller = m_get_item_info_impl_code->GetFunctionCaller(); - if (!func_caller) { - if (log) - log->Printf("Could not retrieve function caller for " - "__introspection_dispatch_queue_item_get_info."); - error.SetErrorString("Could not retrieve function caller for " - "__introspection_dispatch_queue_item_get_info."); - return return_value; - } - - func_call_ret = func_caller->ExecuteFunction(exe_ctx, &args_addr, options, - diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_queue_item_get_info(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_queue_get_item_info() for " - "list of queues"); - return return_value; - } - - return_value.item_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_item_info_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.item_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.item_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_item_info_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - if (log) - log->Printf("AppleGetItemInfoHandler called " - "__introspection_dispatch_queue_item_get_info (page_to_free == " - "0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64, - page_to_free, page_to_free_size, return_value.item_buffer_ptr, - return_value.item_buffer_size); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h deleted file mode 100644 index ac3711ead8783..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h +++ /dev/null @@ -1,115 +0,0 @@ -//===-- AppleGetItemInfoHandler.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetItemInfoHandler_h_ -#define lldb_AppleGetItemInfoHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_queue_item_get_info() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_item_info_return_values -// { -// introspection_dispatch_item_info_ref *item_buffer; -// uint64_t item_buffer_size; -// }; -// -// The item_buffer pointer is an address in the inferior program's address -// space (item_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. -// -// The AppleGetItemInfoHandler object should persist so that the UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetItemInfoHandler { -public: - AppleGetItemInfoHandler(lldb_private::Process *process); - - ~AppleGetItemInfoHandler(); - - struct GetItemInfoReturnInfo { - lldb::addr_t item_buffer_ptr; /* the address of the item buffer from - libBacktraceRecording */ - lldb::addr_t item_buffer_size; /* the size of the item buffer from - libBacktraceRecording */ - - GetItemInfoReturnInfo() - : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {} - }; - - //---------------------------------------------------------- - /// Get the information about a work item by calling - /// __introspection_dispatch_queue_item_get_info. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] item - /// The introspection_dispatch_item_info_ref value for the item of - /// interest. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the item_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetItemInfoReturnInfo GetItemInfo(Thread &thread, lldb::addr_t item, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t SetupGetItemInfoFunction(Thread &thread, - ValueList &get_item_info_arglist); - - static const char *g_get_item_info_function_name; - static const char *g_get_item_info_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_item_info_impl_code; - std::mutex m_get_item_info_function_mutex; - - lldb::addr_t m_get_item_info_return_buffer_addr; - std::mutex m_get_item_info_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetItemInfoHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp deleted file mode 100644 index 78e50e673af0a..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ /dev/null @@ -1,406 +0,0 @@ -//===-- AppleGetPendingItemsHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetPendingItemsHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetPendingItemsHandler::g_get_pending_items_function_name = - "__lldb_backtrace_recording_get_pending_items"; -const char *AppleGetPendingItemsHandler::g_get_pending_items_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern uint64_t __introspection_dispatch_queue_get_pending_items (dispatch_queue_t queue, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_pending_items_return_values \n\ - { \n\ - uint64_t pending_items_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t pending_items_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - uint64_t count; /* the number of items included in the queues buffer */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_pending_items \n\ - (struct get_pending_items_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t /* dispatch_queue_t */ queue, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_pending_items with args return_buffer == %p, debug == %d, queue == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, queue, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - return_buffer->count = __introspection_dispatch_queue_get_pending_items ( \n\ - (void*) queue, \n\ - (void**)&return_buffer->pending_items_buffer_ptr, \n\ - &return_buffer->pending_items_buffer_size); \n\ - if (debug) \n\ - printf(\"result was count %lld\\n\", return_buffer->count); \n\ -} \n\ -} \n\ -"; - -AppleGetPendingItemsHandler::AppleGetPendingItemsHandler(Process *process) - : m_process(process), m_get_pending_items_impl_code(), - m_get_pending_items_function_mutex(), - m_get_pending_items_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_pending_items_retbuffer_mutex() {} - -AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler() {} - -void AppleGetPendingItemsHandler::Detach() { - if (m_process && m_process->IsAlive() && - m_get_pending_items_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_pending_items_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_pending_items_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_pending_items() function (from -// the source above in g_get_pending_items_function_code) if we don't find that -// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g. -// this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_pending_items into the inferior -// process if needed. -// -// Write the get_pending_items_arglist into the inferior's memory space to -// prepare for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction( - Thread &thread, ValueList &get_pending_items_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_pending_items_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_pending_items_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_pending_items_impl_code.get()) { - if (g_get_pending_items_function_code != NULL) { - Status error; - m_get_pending_items_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_pending_items_function_code, eLanguageTypeObjC, - g_get_pending_items_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get UtilityFunction for pending-items " - "introspection: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install pending-items introspection."); - diagnostics.Dump(log); - } - m_get_pending_items_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No pending-items introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Next make the runner function for our implementation utility function. - Status error; - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_pending_items_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - get_pending_items_caller = - m_get_pending_items_impl_code->MakeFunctionCaller( - get_pending_items_return_type, get_pending_items_arglist, - thread_sp, error); - if (error.Fail() || get_pending_items_caller == nullptr) { - if (log) - log->Printf("Failed to install pending-items introspection function " - "caller: %s.", - error.AsCString()); - m_get_pending_items_impl_code.reset(); - return args_addr; - } - } - } - - diagnostics.Clear(); - - if (get_pending_items_caller == nullptr) { - if (log) - log->Printf("Failed to get get_pending_items_caller."); - return LLDB_INVALID_ADDRESS; - } - - // Now write down the argument values for this particular call. This looks - // like it might be a race condition if other threads were calling into here, - // but actually it isn't because we allocate a new args structure for this - // call by passing args_addr = LLDB_INVALID_ADDRESS... - - if (!get_pending_items_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing pending-items function arguments."); - diagnostics.Dump(log); - } - - return args_addr; - } - - return args_addr; -} - -AppleGetPendingItemsHandler::GetPendingItemsReturnInfo -AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetPendingItemsReturnInfo return_value; - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.items_buffer_size = 0; - return_value.count = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_pending_items_return_values - // { - // uint64_t pending_items_buffer_ptr; /* the address of the items - // buffer from libBacktraceRecording */ - // uint64_t pending_items_buffer_size; /* the size of the items buffer - // from libBacktraceRecording */ - // uint64_t count; /* the number of items included in the - // queues buffer */ - // }; - // - // void __lldb_backtrace_recording_get_pending_items - // (struct - // get_pending_items_return_values - // *return_buffer, - // int debug, - // uint64_t /* dispatch_queue_t */ - // queue - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value queue_value; - queue_value.SetValueType(Value::eValueTypeScalar); - queue_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_pending_items_retbuffer_mutex); - if (m_get_pending_items_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_pending_items_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_pending_items_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - queue_value.GetScalar() = queue; - argument_values.PushValue(queue_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetPendingItemsFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - FunctionCaller *get_pending_items_caller = - m_get_pending_items_impl_code->GetFunctionCaller(); - - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (get_pending_items_caller == NULL) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_queue_get_pending_items"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_pending_items_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_queue_get_pending_items(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_queue_get_pending_items() " - "for list of queues"); - return return_value; - } - - return_value.items_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.items_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.items_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.count = m_process->ReadUnsignedIntegerFromMemory( - m_get_pending_items_return_buffer_addr + 16, 8, 0, error); - if (!error.Success()) { - return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetPendingItemsHandler called " - "__introspection_dispatch_queue_get_pending_items " - "(page_to_free == 0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64 - ", count = %" PRId64, - page_to_free, page_to_free_size, return_value.items_buffer_ptr, - return_value.items_buffer_size, return_value.count); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h deleted file mode 100644 index d35a72c2ff432..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h +++ /dev/null @@ -1,120 +0,0 @@ -//===-- AppleGetPendingItemsHandler.h ----------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetPendingItemsHandler_h_ -#define lldb_AppleGetPendingItemsHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_queue_get_pending_items() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_pending_items_return_values -// { -// introspection_dispatch_item_info_ref *items_buffer; -// uint64_t items_buffer_size; -// uint64_t count; -// }; -// -// The items_buffer pointer is an address in the inferior program's address -// space (items_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. count is the number of items that were stored in the buffer. -// -// The AppleGetPendingItemsHandler object should persist so that the -// UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetPendingItemsHandler { -public: - AppleGetPendingItemsHandler(lldb_private::Process *process); - - ~AppleGetPendingItemsHandler(); - - struct GetPendingItemsReturnInfo { - lldb::addr_t items_buffer_ptr; /* the address of the pending items buffer - from libBacktraceRecording */ - lldb::addr_t - items_buffer_size; /* the size of the pending items buffer from - libBacktraceRecording */ - uint64_t count; /* the number of pending items included in the buffer */ - - GetPendingItemsReturnInfo() - : items_buffer_ptr(LLDB_INVALID_ADDRESS), items_buffer_size(0), - count(0) {} - }; - - //---------------------------------------------------------- - /// Get the list of pending items for a given queue via a call to - /// __introspection_dispatch_queue_get_pending_items. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] queue - /// The dispatch_queue_t value for the queue of interest. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the items_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetPendingItemsReturnInfo GetPendingItems(Thread &thread, lldb::addr_t queue, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t - SetupGetPendingItemsFunction(Thread &thread, - ValueList &get_pending_items_arglist); - - static const char *g_get_pending_items_function_name; - static const char *g_get_pending_items_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_pending_items_impl_code; - std::mutex m_get_pending_items_function_mutex; - - lldb::addr_t m_get_pending_items_return_buffer_addr; - std::mutex m_get_pending_items_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetPendingItemsHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp deleted file mode 100644 index 245ff6742b439..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ /dev/null @@ -1,403 +0,0 @@ -//===-- AppleGetQueuesHandler.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetQueuesHandler.h" - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb; -using namespace lldb_private; - -const char *AppleGetQueuesHandler::g_get_current_queues_function_name = - "__lldb_backtrace_recording_get_current_queues"; -const char *AppleGetQueuesHandler::g_get_current_queues_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - \n\ - extern uint64_t __introspection_dispatch_get_queues (queue_list_scope_t scope, \n\ - introspection_dispatch_queue_info_t *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - extern int printf(const char *format, ...); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_current_queues_return_values \n\ - { \n\ - uint64_t queues_buffer_ptr; /* the address of the queues buffer from libBacktraceRecording */ \n\ - uint64_t queues_buffer_size; /* the size of the queues buffer from libBacktraceRecording */ \n\ - uint64_t count; /* the number of queues included in the queues buffer */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_current_queues \n\ - (struct get_current_queues_return_values *return_buffer, \n\ - int debug, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - if (debug) \n\ - printf (\"entering get_current_queues with args %p, %d, 0x%p, 0x%llx\\n\", return_buffer, debug, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - return_buffer->count = __introspection_dispatch_get_queues ( \n\ - /* QUEUES_WITH_ANY_ITEMS */ 2, \n\ - (void**)&return_buffer->queues_buffer_ptr, \n\ - &return_buffer->queues_buffer_size); \n\ - if (debug) \n\ - printf(\"result was count %lld\\n\", return_buffer->count); \n\ -} \n\ -} \n\ -"; - -AppleGetQueuesHandler::AppleGetQueuesHandler(Process *process) - : m_process(process), m_get_queues_impl_code_up(), - m_get_queues_function_mutex(), - m_get_queues_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_queues_retbuffer_mutex() {} - -AppleGetQueuesHandler::~AppleGetQueuesHandler() {} - -void AppleGetQueuesHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_queues_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_queues_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_queues_return_buffer_addr); - } -} - -// Construct a CompilerType for the structure that -// g_get_current_queues_function_code will return by value so we can extract -// the fields after performing the function call. i.e. we are getting this -// struct returned to us: -// -// struct get_current_queues_return_values -// { -// introspection_dispatch_queue_info_t *queues_buffer; -// uint64_t queues_buffer_size; -// uint64_t count; -// }; - -// Compile our __lldb_backtrace_recording_get_current_queues() function (from -// the source above in g_get_current_queues_function_code) if we don't find -// that function in the inferior already with USE_BUILTIN_FUNCTION defined. -// (e.g. this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_current_queues into the inferior -// process if needed. -// -// Write the get_queues_arglist into the inferior's memory space to prepare for -// the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t -AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread, - ValueList &get_queues_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - - Address impl_code_address; - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - - FunctionCaller *get_queues_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_queues_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_queues_impl_code_up.get()) { - if (g_get_current_queues_function_code != NULL) { - Status error; - m_get_queues_impl_code_up.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_current_queues_function_code, eLanguageTypeC, - g_get_current_queues_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf( - "Failed to get UtilityFunction for queues introspection: %s.", - error.AsCString()); - return args_addr; - } - - if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf("Failed to install queues introspection"); - diagnostics.Dump(log); - } - m_get_queues_impl_code_up.reset(); - return args_addr; - } - } else { - if (log) { - log->Printf("No queues introspection code found."); - diagnostics.Dump(log); - } - return LLDB_INVALID_ADDRESS; - } - } - - // Next make the runner function for our implementation utility function. - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_queues_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Status error; - get_queues_caller = m_get_queues_impl_code_up->MakeFunctionCaller( - get_queues_return_type, get_queues_arglist, thread_sp, error); - if (error.Fail() || get_queues_caller == nullptr) { - if (log) - log->Printf( - "Could not get function caller for get-queues function: %s.", - error.AsCString()); - return args_addr; - } - } - - diagnostics.Clear(); - - // Now write down the argument values for this particular call. This looks - // like it might be a race condition if other threads were calling into here, - // but actually it isn't because we allocate a new args structure for this - // call by passing args_addr = LLDB_INVALID_ADDRESS... - - if (!get_queues_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_queues_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-queues function arguments."); - diagnostics.Dump(log); - } - return args_addr; - } - - return args_addr; -} - -AppleGetQueuesHandler::GetQueuesReturnInfo -AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetQueuesReturnInfo return_value; - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.queues_buffer_size = 0; - return_value.count = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_current_queues_return_values - // { - // uint64_t queues_buffer_ptr; /* the address of the queues buffer from - // libBacktraceRecording */ - // uint64_t queues_buffer_size; /* the size of the queues buffer from - // libBacktraceRecording */ - // uint64_t count; /* the number of queues included in the - // queues buffer */ - // }; - // - // void - // __lldb_backtrace_recording_get_current_queues - // (struct - // get_current_queues_return_values - // *return_buffer, - // void *page_to_free, - // uint64_t page_to_free_size); - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_queues_retbuffer_mutex); - if (m_get_queues_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_queues_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = m_get_queues_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetQueuesFunction(thread, argument_values); - - if (!m_get_queues_impl_code_up) { - error.SetErrorString( - "Unable to compile __introspection_dispatch_get_queues."); - return return_value; - } - - FunctionCaller *get_queues_caller = - m_get_queues_impl_code_up->GetFunctionCaller(); - - if (get_queues_caller == NULL) { - error.SetErrorString( - "Unable to get caller for call __introspection_dispatch_get_queues"); - return return_value; - } - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_queues_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call introspection_get_dispatch_queues(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call introspection_get_dispatch_queues() " - "for list of queues"); - return return_value; - } - - return_value.queues_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); - if (!error.Success() || - return_value.queues_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.queues_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.count = m_process->ReadUnsignedIntegerFromMemory( - m_get_queues_return_buffer_addr + 16, 8, 0, error); - if (!error.Success()) { - return_value.queues_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetQueuesHandler called " - "__introspection_dispatch_get_queues (page_to_free == " - "0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64 - ", count = %" PRId64, - page_to_free, page_to_free_size, return_value.queues_buffer_ptr, - return_value.queues_buffer_size, return_value.count); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h deleted file mode 100644 index 0d8e4dc64a685..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h +++ /dev/null @@ -1,112 +0,0 @@ -//===-- AppleGetQueuesHandler.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetQueuesHandler_h_ -#define lldb_AppleGetQueuesHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's introspection_get_dispatch_queues() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_current_queues_return_values -// { -// introspection_dispatch_queue_info_t *queues_buffer; -// uint64_t queues_buffer_size; -// uint64_t count; -// }; -// -// The queues_buffer pointer is an address in the inferior program's address -// space (queues_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. count is the number of queues that were stored in the buffer. -// -// The AppleGetQueuesHandler object should persist so that the UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetQueuesHandler { -public: - AppleGetQueuesHandler(lldb_private::Process *process); - - ~AppleGetQueuesHandler(); - - struct GetQueuesReturnInfo { - lldb::addr_t queues_buffer_ptr; /* the address of the queues buffer from - libBacktraceRecording */ - lldb::addr_t queues_buffer_size; /* the size of the queues buffer from - libBacktraceRecording */ - uint64_t count; /* the number of queues included in the queues buffer */ - - GetQueuesReturnInfo() - : queues_buffer_ptr(LLDB_INVALID_ADDRESS), queues_buffer_size(0), - count(0) {} - }; - - //---------------------------------------------------------- - /// Get the list of queues that exist (with any active or pending items) via - /// a call to introspection_get_dispatch_queues(). If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread - /// The thread to run this plan on. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the queues_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetQueuesReturnInfo GetCurrentQueues(Thread &thread, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t SetupGetQueuesFunction(Thread &thread, - ValueList &get_queues_arglist); - - static const char *g_get_current_queues_function_name; - static const char *g_get_current_queues_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_queues_impl_code_up; - std::mutex m_get_queues_function_mutex; - - lldb::addr_t m_get_queues_return_buffer_addr; - std::mutex m_get_queues_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetQueuesHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp deleted file mode 100644 index ede81333a3e67..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ /dev/null @@ -1,410 +0,0 @@ -//===-- AppleGetThreadItemInfoHandler.cpp -------------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "AppleGetThreadItemInfoHandler.h" - - -#include "lldb/Core/Module.h" -#include "lldb/Core/Value.h" -#include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/Expression.h" -#include "lldb/Expression/FunctionCaller.h" -#include "lldb/Expression/UtilityFunction.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/Symbol.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" -#include "lldb/lldb-private.h" - -using namespace lldb; -using namespace lldb_private; - -const char - *AppleGetThreadItemInfoHandler::g_get_thread_item_info_function_name = - "__lldb_backtrace_recording_get_thread_item_info"; -const char - *AppleGetThreadItemInfoHandler::g_get_thread_item_info_function_code = - " \n\ -extern \"C\" \n\ -{ \n\ - /* \n\ - * mach defines \n\ - */ \n\ - \n\ - typedef unsigned int uint32_t; \n\ - typedef unsigned long long uint64_t; \n\ - typedef uint32_t mach_port_t; \n\ - typedef mach_port_t vm_map_t; \n\ - typedef int kern_return_t; \n\ - typedef uint64_t mach_vm_address_t; \n\ - typedef uint64_t mach_vm_size_t; \n\ - \n\ - mach_port_t mach_task_self (); \n\ - kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ - \n\ - typedef void *pthread_t; \n\ - extern int printf(const char *format, ...); \n\ - extern pthread_t pthread_self(void); \n\ - \n\ - /* \n\ - * libBacktraceRecording defines \n\ - */ \n\ - \n\ - typedef uint32_t queue_list_scope_t; \n\ - typedef void *dispatch_queue_t; \n\ - typedef void *introspection_dispatch_queue_info_t; \n\ - typedef void *introspection_dispatch_item_info_ref; \n\ - \n\ - extern void __introspection_dispatch_thread_get_item_info (uint64_t thread_id, \n\ - introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ - uint64_t *returned_queues_buffer_size); \n\ - \n\ - /* \n\ - * return type define \n\ - */ \n\ - \n\ - struct get_thread_item_info_return_values \n\ - { \n\ - uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ - uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ - }; \n\ - \n\ - void __lldb_backtrace_recording_get_thread_item_info \n\ - (struct get_thread_item_info_return_values *return_buffer, \n\ - int debug, \n\ - uint64_t thread_id, \n\ - void *page_to_free, \n\ - uint64_t page_to_free_size) \n\ -{ \n\ - void *pthread_id = pthread_self (); \n\ - if (debug) \n\ - printf (\"entering get_thread_item_info with args return_buffer == %p, debug == %d, thread id == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, (uint64_t) thread_id, page_to_free, page_to_free_size); \n\ - if (page_to_free != 0) \n\ - { \n\ - mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ - } \n\ - \n\ - __introspection_dispatch_thread_get_item_info (thread_id, \n\ - (void**)&return_buffer->item_info_buffer_ptr, \n\ - &return_buffer->item_info_buffer_size); \n\ -} \n\ -} \n\ -"; - -AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler(Process *process) - : m_process(process), m_get_thread_item_info_impl_code(), - m_get_thread_item_info_function_mutex(), - m_get_thread_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), - m_get_thread_item_info_retbuffer_mutex() {} - -AppleGetThreadItemInfoHandler::~AppleGetThreadItemInfoHandler() {} - -void AppleGetThreadItemInfoHandler::Detach() { - - if (m_process && m_process->IsAlive() && - m_get_thread_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - std::unique_lock<std::mutex> lock(m_get_thread_item_info_retbuffer_mutex, - std::defer_lock); - lock.try_lock(); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory(m_get_thread_item_info_return_buffer_addr); - } -} - -// Compile our __lldb_backtrace_recording_get_thread_item_info() function (from -// the source above in g_get_thread_item_info_function_code) if we don't find -// that function in the inferior already with USE_BUILTIN_FUNCTION defined. -// (e.g. this would be the case for testing.) -// -// Insert the __lldb_backtrace_recording_get_thread_item_info into the inferior -// process if needed. -// -// Write the get_thread_item_info_arglist into the inferior's memory space to -// prepare for the call. -// -// Returns the address of the arguments written down in the inferior process, -// which can be used to make the function call. - -lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction( - Thread &thread, ValueList &get_thread_item_info_arglist) { - ThreadSP thread_sp(thread.shared_from_this()); - ExecutionContext exe_ctx(thread_sp); - Address impl_code_address; - DiagnosticManager diagnostics; - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - FunctionCaller *get_thread_item_info_caller = nullptr; - - // Scope for mutex locker: - { - std::lock_guard<std::mutex> guard(m_get_thread_item_info_function_mutex); - - // First stage is to make the ClangUtility to hold our injected function: - - if (!m_get_thread_item_info_impl_code.get()) { - Status error; - if (g_get_thread_item_info_function_code != NULL) { - m_get_thread_item_info_impl_code.reset( - exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( - g_get_thread_item_info_function_code, eLanguageTypeC, - g_get_thread_item_info_function_name, error)); - if (error.Fail()) { - if (log) - log->Printf("Failed to get UtilityFunction for " - "get-thread-item-info introspection: %s.", - error.AsCString()); - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - - if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) { - if (log) { - log->Printf( - "Failed to install get-thread-item-info introspection."); - diagnostics.Dump(log); - } - - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - } else { - if (log) - log->Printf("No get-thread-item-info introspection code found."); - return LLDB_INVALID_ADDRESS; - } - - // Also make the FunctionCaller for this UtilityFunction: - - ClangASTContext *clang_ast_context = - thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_thread_item_info_return_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->MakeFunctionCaller( - get_thread_item_info_return_type, get_thread_item_info_arglist, - thread_sp, error); - if (error.Fail() || get_thread_item_info_caller == nullptr) { - if (log) - log->Printf("Failed to install get-thread-item-info introspection " - "caller: %s.", - error.AsCString()); - m_get_thread_item_info_impl_code.reset(); - return args_addr; - } - - } else { - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->GetFunctionCaller(); - } - } - - diagnostics.Clear(); - - // Now write down the argument values for this particular call. This looks - // like it might be a race condition if other threads were calling into here, - // but actually it isn't because we allocate a new args structure for this - // call by passing args_addr = LLDB_INVALID_ADDRESS... - - if (!get_thread_item_info_caller->WriteFunctionArguments( - exe_ctx, args_addr, get_thread_item_info_arglist, diagnostics)) { - if (log) { - log->Printf("Error writing get-thread-item-info function arguments"); - diagnostics.Dump(log); - } - return args_addr; - } - - return args_addr; -} - -AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo -AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread, - tid_t thread_id, - addr_t page_to_free, - uint64_t page_to_free_size, - Status &error) { - lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); - ProcessSP process_sp(thread.CalculateProcess()); - TargetSP target_sp(thread.CalculateTarget()); - ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - - GetThreadItemInfoReturnInfo return_value; - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return_value.item_buffer_size = 0; - - error.Clear(); - - if (!thread.SafeToCallFunctions()) { - if (log) - log->Printf("Not safe to call functions on thread 0x%" PRIx64, - thread.GetID()); - error.SetErrorString("Not safe to call functions on this thread."); - return return_value; - } - - // Set up the arguments for a call to - - // struct get_thread_item_info_return_values { - // uint64_t item_info_buffer_ptr; /* the address of the items buffer - // from libBacktraceRecording */ - // uint64_t item_info_buffer_size; /* the size of the items buffer from - // libBacktraceRecording */ - // }; - // - // void __lldb_backtrace_recording_get_thread_item_info - // (struct - // get_thread_item_info_return_values - // *return_buffer, - // int debug, - // void *page_to_free, - // uint64_t page_to_free_size) - - // Where the return_buffer argument points to a 24 byte region of memory - // already allocated by lldb in the inferior process. - - CompilerType clang_void_ptr_type = - clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - Value return_buffer_ptr_value; - return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); - return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); - - CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); - Value debug_value; - debug_value.SetValueType(Value::eValueTypeScalar); - debug_value.SetCompilerType(clang_int_type); - - CompilerType clang_uint64_type = - clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); - Value thread_id_value; - thread_id_value.SetValueType(Value::eValueTypeScalar); - thread_id_value.SetCompilerType(clang_uint64_type); - - Value page_to_free_value; - page_to_free_value.SetValueType(Value::eValueTypeScalar); - page_to_free_value.SetCompilerType(clang_void_ptr_type); - - Value page_to_free_size_value; - page_to_free_size_value.SetValueType(Value::eValueTypeScalar); - page_to_free_size_value.SetCompilerType(clang_uint64_type); - - std::lock_guard<std::mutex> guard(m_get_thread_item_info_retbuffer_mutex); - if (m_get_thread_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { - addr_t bufaddr = process_sp->AllocateMemory( - 32, ePermissionsReadable | ePermissionsWritable, error); - if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { - if (log) - log->Printf("Failed to allocate memory for return buffer for get " - "current queues func call"); - return return_value; - } - m_get_thread_item_info_return_buffer_addr = bufaddr; - } - - ValueList argument_values; - - return_buffer_ptr_value.GetScalar() = - m_get_thread_item_info_return_buffer_addr; - argument_values.PushValue(return_buffer_ptr_value); - - debug_value.GetScalar() = 0; - argument_values.PushValue(debug_value); - - thread_id_value.GetScalar() = thread_id; - argument_values.PushValue(thread_id_value); - - if (page_to_free != LLDB_INVALID_ADDRESS) - page_to_free_value.GetScalar() = page_to_free; - else - page_to_free_value.GetScalar() = 0; - argument_values.PushValue(page_to_free_value); - - page_to_free_size_value.GetScalar() = page_to_free_size; - argument_values.PushValue(page_to_free_size_value); - - addr_t args_addr = SetupGetThreadItemInfoFunction(thread, argument_values); - - DiagnosticManager diagnostics; - ExecutionContext exe_ctx; - EvaluateExpressionOptions options; - FunctionCaller *get_thread_item_info_caller = nullptr; - - options.SetUnwindOnError(true); - options.SetIgnoreBreakpoints(true); - options.SetStopOthers(true); - options.SetTimeout(std::chrono::milliseconds(500)); - options.SetTryAllThreads(false); - options.SetIsForUtilityExpr(true); - thread.CalculateExecutionContext(exe_ctx); - - if (!m_get_thread_item_info_impl_code) { - error.SetErrorString("Unable to compile function to call " - "__introspection_dispatch_thread_get_item_info"); - return return_value; - } - - get_thread_item_info_caller = - m_get_thread_item_info_impl_code->GetFunctionCaller(); - - if (!get_thread_item_info_caller) { - error.SetErrorString("Unable to compile function caller for " - "__introspection_dispatch_thread_get_item_info"); - return return_value; - } - - ExpressionResults func_call_ret; - Value results; - func_call_ret = get_thread_item_info_caller->ExecuteFunction( - exe_ctx, &args_addr, options, diagnostics, results); - if (func_call_ret != eExpressionCompleted || !error.Success()) { - if (log) - log->Printf("Unable to call " - "__introspection_dispatch_thread_get_item_info(), got " - "ExpressionResults %d, error contains %s", - func_call_ret, error.AsCString("")); - error.SetErrorString("Unable to call " - "__introspection_dispatch_thread_get_item_info() for " - "list of queues"); - return return_value; - } - - return_value.item_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( - m_get_thread_item_info_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, - error); - if (!error.Success() || - return_value.item_buffer_ptr == LLDB_INVALID_ADDRESS) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - return_value.item_buffer_size = m_process->ReadUnsignedIntegerFromMemory( - m_get_thread_item_info_return_buffer_addr + 8, 8, 0, error); - - if (!error.Success()) { - return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; - return return_value; - } - - if (log) - log->Printf("AppleGetThreadItemInfoHandler called " - "__introspection_dispatch_thread_get_item_info (page_to_free " - "== 0x%" PRIx64 ", size = %" PRId64 - "), returned page is at 0x%" PRIx64 ", size %" PRId64, - page_to_free, page_to_free_size, return_value.item_buffer_ptr, - return_value.item_buffer_size); - - return return_value; -} diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h deleted file mode 100644 index 47e1961023629..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h +++ /dev/null @@ -1,114 +0,0 @@ -//===-- AppleGetThreadItemInfoHandler.h ----------------------------*- C++ -//-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef lldb_AppleGetThreadItemInfoHandler_h_ -#define lldb_AppleGetThreadItemInfoHandler_h_ - -#include <map> -#include <mutex> -#include <vector> - -#include "lldb/Symbol/CompilerType.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-public.h" - -// This class will insert a UtilityFunction into the inferior process for -// calling libBacktraceRecording's -// __introspection_dispatch_thread_get_item_info() -// function. The function in the inferior will return a struct by value -// with these members: -// -// struct get_thread_item_info_return_values -// { -// introspection_dispatch_item_info_ref *item_buffer; -// uint64_t item_buffer_size; -// }; -// -// The item_buffer pointer is an address in the inferior program's address -// space (item_buffer_size in size) which must be mach_vm_deallocate'd by -// lldb. -// -// The AppleGetThreadItemInfoHandler object should persist so that the -// UtilityFunction -// can be reused multiple times. - -namespace lldb_private { - -class AppleGetThreadItemInfoHandler { -public: - AppleGetThreadItemInfoHandler(lldb_private::Process *process); - - ~AppleGetThreadItemInfoHandler(); - - struct GetThreadItemInfoReturnInfo { - lldb::addr_t item_buffer_ptr; /* the address of the item buffer from - libBacktraceRecording */ - lldb::addr_t item_buffer_size; /* the size of the item buffer from - libBacktraceRecording */ - - GetThreadItemInfoReturnInfo() - : item_buffer_ptr(LLDB_INVALID_ADDRESS), item_buffer_size(0) {} - }; - - //---------------------------------------------------------- - /// Get the information about a work item by calling - /// __introspection_dispatch_thread_get_item_info. If there's a page of - /// memory that needs to be freed, pass in the address and size and it will - /// be freed before getting the list of queues. - /// - /// @param [in] thread_id - /// The thread to get the extended backtrace for. - /// - /// @param [in] page_to_free - /// An address of an inferior process vm page that needs to be - /// deallocated, - /// LLDB_INVALID_ADDRESS if this is not needed. - /// - /// @param [in] page_to_free_size - /// The size of the vm page that needs to be deallocated if an address was - /// passed in to page_to_free. - /// - /// @param [out] error - /// This object will be updated with the error status / error string from - /// any failures encountered. - /// - /// @returns - /// The result of the inferior function call execution. If there was a - /// failure of any kind while getting - /// the information, the item_buffer_ptr value will be - /// LLDB_INVALID_ADDRESS. - //---------------------------------------------------------- - GetThreadItemInfoReturnInfo GetThreadItemInfo(Thread &thread, - lldb::tid_t thread_id, - lldb::addr_t page_to_free, - uint64_t page_to_free_size, - lldb_private::Status &error); - - void Detach(); - -private: - lldb::addr_t - SetupGetThreadItemInfoFunction(Thread &thread, - ValueList &get_thread_item_info_arglist); - - static const char *g_get_thread_item_info_function_name; - static const char *g_get_thread_item_info_function_code; - - lldb_private::Process *m_process; - std::unique_ptr<UtilityFunction> m_get_thread_item_info_impl_code; - std::mutex m_get_thread_item_info_function_mutex; - - lldb::addr_t m_get_thread_item_info_return_buffer_addr; - std::mutex m_get_thread_item_info_retbuffer_mutex; -}; - -} // using namespace lldb_private - -#endif // lldb_AppleGetThreadItemInfoHandler_h_ diff --git a/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt b/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt deleted file mode 100644 index ac5781b98b09c..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -add_lldb_library(lldbPluginSystemRuntimeMacOSX PLUGIN - AppleGetItemInfoHandler.cpp - AppleGetPendingItemsHandler.cpp - AppleGetQueuesHandler.cpp - AppleGetThreadItemInfoHandler.cpp - SystemRuntimeMacOSX.cpp - - LINK_LIBS - lldbBreakpoint - lldbCore - lldbExpression - lldbHost - lldbSymbol - lldbTarget - lldbUtility - lldbPluginProcessUtility - ) diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp deleted file mode 100644 index e61f04e489e84..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ /dev/null @@ -1,1021 +0,0 @@ -//===-- SystemRuntimeMacOSX.cpp ---------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "Plugins/Process/Utility/HistoryThread.h" -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessStructReader.h" -#include "lldb/Target/Queue.h" -#include "lldb/Target/QueueList.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataExtractor.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/StreamString.h" - -#include "SystemRuntimeMacOSX.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// Create an instance of this class. This function is filled into the plugin -// info class that gets handed out by the plugin factory and allows the lldb to -// instantiate an instance of this class. -//---------------------------------------------------------------------- -SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) { - bool create = false; - if (!create) { - create = true; - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) { - ObjectFile *object_file = exe_module->GetObjectFile(); - if (object_file) { - create = (object_file->GetStrata() == ObjectFile::eStrataUser); - } - } - - if (create) { - const llvm::Triple &triple_ref = - process->GetTarget().GetArchitecture().GetTriple(); - switch (triple_ref.getOS()) { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: - create = triple_ref.getVendor() == llvm::Triple::Apple; - break; - default: - create = false; - break; - } - } - } - - if (create) - return new SystemRuntimeMacOSX(process); - return NULL; -} - -//---------------------------------------------------------------------- -// Constructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process) - : SystemRuntime(process), m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(), - m_get_queues_handler(process), m_get_pending_items_handler(process), - m_get_item_info_handler(process), m_get_thread_item_info_handler(process), - m_page_to_free(LLDB_INVALID_ADDRESS), m_page_to_free_size(0), - m_lib_backtrace_recording_info(), - m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_offsets(), - m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS), - m_libpthread_offsets(), m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_tsd_indexes(), - m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS), - m_libdispatch_voucher_offsets() {} - -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -SystemRuntimeMacOSX::~SystemRuntimeMacOSX() { Clear(true); } - -void SystemRuntimeMacOSX::Detach() { - m_get_queues_handler.Detach(); - m_get_pending_items_handler.Detach(); - m_get_item_info_handler.Detach(); - m_get_thread_item_info_handler.Detach(); -} - -//---------------------------------------------------------------------- -// Clear out the state of this class. -//---------------------------------------------------------------------- -void SystemRuntimeMacOSX::Clear(bool clear_process) { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) - m_process->ClearBreakpointSiteByID(m_break_id); - - if (clear_process) - m_process = NULL; - m_break_id = LLDB_INVALID_BREAK_ID; -} - -std::string -SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) { - std::string dispatch_queue_name; - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return ""; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - addr_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - if (m_libdispatch_offsets.dqo_version >= 4) { - // libdispatch versions 4+, pointer to dispatch name is in the queue - // structure. - addr_t pointer_to_label_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - addr_t label_addr = - m_process->ReadPointerFromMemory(pointer_to_label_address, error); - if (error.Success()) { - m_process->ReadCStringFromMemory(label_addr, dispatch_queue_name, - error); - } - } else { - // libdispatch versions 1-3, dispatch name is a fixed width char array - // in the queue structure. - addr_t label_addr = - dispatch_queue_addr + m_libdispatch_offsets.dqo_label; - dispatch_queue_name.resize(m_libdispatch_offsets.dqo_label_size, '\0'); - size_t bytes_read = - m_process->ReadMemory(label_addr, &dispatch_queue_name[0], - m_libdispatch_offsets.dqo_label_size, error); - if (bytes_read < m_libdispatch_offsets.dqo_label_size) - dispatch_queue_name.erase(bytes_read); - } - } - } - return dispatch_queue_name; -} - -lldb::addr_t SystemRuntimeMacOSX::GetLibdispatchQueueAddressFromThreadQAddress( - addr_t dispatch_qaddr) { - addr_t libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - Status error; - libdispatch_queue_t_address = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (!error.Success()) { - libdispatch_queue_t_address = LLDB_INVALID_ADDRESS; - } - return libdispatch_queue_t_address; -} - -lldb::QueueKind SystemRuntimeMacOSX::GetQueueKind(addr_t dispatch_queue_addr) { - if (dispatch_queue_addr == LLDB_INVALID_ADDRESS || dispatch_queue_addr == 0) - return eQueueKindUnknown; - - QueueKind kind = eQueueKindUnknown; - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid() && - m_libdispatch_offsets.dqo_version >= 4) { - Status error; - uint64_t width = m_process->ReadUnsignedIntegerFromMemory( - dispatch_queue_addr + m_libdispatch_offsets.dqo_width, - m_libdispatch_offsets.dqo_width_size, 0, error); - if (error.Success()) { - if (width == 1) { - kind = eQueueKindSerial; - } - if (width > 1) { - kind = eQueueKindConcurrent; - } - } - } - return kind; -} - -void SystemRuntimeMacOSX::AddThreadExtendedInfoPacketHints( - lldb_private::StructuredData::ObjectSP dict_sp) { - StructuredData::Dictionary *dict = dict_sp->GetAsDictionary(); - if (dict) { - ReadLibpthreadOffsets(); - if (m_libpthread_offsets.IsValid()) { - dict->AddIntegerItem("plo_pthread_tsd_base_offset", - m_libpthread_offsets.plo_pthread_tsd_base_offset); - dict->AddIntegerItem( - "plo_pthread_tsd_base_address_offset", - m_libpthread_offsets.plo_pthread_tsd_base_address_offset); - dict->AddIntegerItem("plo_pthread_tsd_entry_size", - m_libpthread_offsets.plo_pthread_tsd_entry_size); - } - - ReadLibdispatchTSDIndexes(); - if (m_libdispatch_tsd_indexes.IsValid()) { - dict->AddIntegerItem("dti_queue_index", - m_libdispatch_tsd_indexes.dti_queue_index); - dict->AddIntegerItem("dti_voucher_index", - m_libdispatch_tsd_indexes.dti_voucher_index); - dict->AddIntegerItem("dti_qos_class_index", - m_libdispatch_tsd_indexes.dti_qos_class_index); - } - } -} - -bool SystemRuntimeMacOSX::SafeToCallFunctionsOnThisThread(ThreadSP thread_sp) { - if (thread_sp && thread_sp->GetStackFrameCount() > 0 && - thread_sp->GetFrameWithConcreteFrameIndex(0)) { - const SymbolContext sym_ctx( - thread_sp->GetFrameWithConcreteFrameIndex(0)->GetSymbolContext( - eSymbolContextSymbol)); - static ConstString g_select_symbol("__select"); - if (sym_ctx.GetFunctionName() == g_select_symbol) { - return false; - } - } - return true; -} - -lldb::queue_id_t -SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) { - queue_id_t queue_id = LLDB_INVALID_QUEUE_ID; - - if (dispatch_qaddr == LLDB_INVALID_ADDRESS || dispatch_qaddr == 0) - return queue_id; - - ReadLibdispatchOffsets(); - if (m_libdispatch_offsets.IsValid()) { - // dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a - // thread - deref it to get the address of the dispatch_queue_t structure - // for this thread's queue. - Status error; - uint64_t dispatch_queue_addr = - m_process->ReadPointerFromMemory(dispatch_qaddr, error); - if (error.Success()) { - addr_t serialnum_address = - dispatch_queue_addr + m_libdispatch_offsets.dqo_serialnum; - queue_id_t serialnum = m_process->ReadUnsignedIntegerFromMemory( - serialnum_address, m_libdispatch_offsets.dqo_serialnum_size, - LLDB_INVALID_QUEUE_ID, error); - if (error.Success()) { - queue_id = serialnum; - } - } - } - - return queue_id; -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() { - if (m_dispatch_queue_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_dispatch_queue_offsets_symbol_name( - "dispatch_queue_offsets"); - const Symbol *dispatch_queue_offsets_symbol = NULL; - - // libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6 - // ("Snow Leopard") - ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libSystem_module_spec)); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - - // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") - // and later - if (dispatch_queue_offsets_symbol == NULL) { - ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib")); - module_sp = m_process->GetTarget().GetImages().FindFirstModule( - libdispatch_module_spec); - if (module_sp) - dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); - } - if (dispatch_queue_offsets_symbol) - m_dispatch_queue_offsets_addr = - dispatch_queue_offsets_symbol->GetLoadAddress(&m_process->GetTarget()); -} - -void SystemRuntimeMacOSX::ReadLibdispatchOffsets() { - if (m_libdispatch_offsets.IsValid()) - return; - - ReadLibdispatchOffsetsAddress(); - - uint8_t memory_buffer[sizeof(struct LibdispatchOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - Status error; - if (m_process->ReadMemory(m_dispatch_queue_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibdispatchOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version, - sizeof(struct LibdispatchOffsets) / sizeof(uint16_t)); - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() { - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libpthread_layout_offsets_symbol_name( - "pthread_layout_offsets"); - const Symbol *libpthread_layout_offsets_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libpthread_layout_offsets_symbol = - module_sp->FindFirstSymbolWithNameAndType( - g_libpthread_layout_offsets_symbol_name, eSymbolTypeData); - if (libpthread_layout_offsets_symbol) { - m_libpthread_layout_offsets_addr = - libpthread_layout_offsets_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibpthreadOffsets() { - if (m_libpthread_offsets.IsValid()) - return; - - ReadLibpthreadOffsetsAddress(); - - if (m_libpthread_layout_offsets_addr != LLDB_INVALID_ADDRESS) { - uint8_t memory_buffer[sizeof(struct LibpthreadOffsets)]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - Status error; - if (m_process->ReadMemory(m_libpthread_layout_offsets_addr, memory_buffer, - sizeof(memory_buffer), - error) == sizeof(memory_buffer)) { - lldb::offset_t data_offset = 0; - - // The struct LibpthreadOffsets is a series of uint16_t's - extract them - // all in one big go. - data.GetU16(&data_offset, &m_libpthread_offsets.plo_version, - sizeof(struct LibpthreadOffsets) / sizeof(uint16_t)); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() { - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) - return; - - static ConstString g_libdispatch_tsd_indexes_symbol_name( - "dispatch_tsd_indexes"); - const Symbol *libdispatch_tsd_indexes_symbol = NULL; - - ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib")); - ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule( - libpthread_module_spec)); - if (module_sp) { - libdispatch_tsd_indexes_symbol = module_sp->FindFirstSymbolWithNameAndType( - g_libdispatch_tsd_indexes_symbol_name, eSymbolTypeData); - if (libdispatch_tsd_indexes_symbol) { - m_dispatch_tsd_indexes_addr = - libdispatch_tsd_indexes_symbol->GetLoadAddress( - &m_process->GetTarget()); - } - } -} - -void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() { - if (m_libdispatch_tsd_indexes.IsValid()) - return; - - ReadLibdispatchTSDIndexesAddress(); - - if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - -// We don't need to check the version number right now, it will be at least 2, -// but keep this code around to fetch just the version # for the future where -// we need to fetch alternate versions of the struct. -#if 0 - uint16_t dti_version = 2; - Address dti_struct_addr; - if (m_process->GetTarget().ResolveLoadAddress (m_dispatch_tsd_indexes_addr, dti_struct_addr)) - { - Status error; - uint16_t version = m_process->GetTarget().ReadUnsignedIntegerFromMemory (dti_struct_addr, false, 2, UINT16_MAX, error); - if (error.Success() && dti_version != UINT16_MAX) - { - dti_version = version; - } - } -#endif - - ClangASTContext *ast_ctx = - m_process->GetTarget().GetScratchClangASTContext(); - if (ast_ctx->getASTContext() && - m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) { - CompilerType uint16 = - ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); - CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType( - nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", - clang::TTK_Struct, lldb::eLanguageTypeC); - - ClangASTContext::StartTagDeclarationDefinition(dispatch_tsd_indexes_s); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_version", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_queue_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_voucher_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::AddFieldToRecordType(dispatch_tsd_indexes_s, - "dti_qos_class_index", uint16, - lldb::eAccessPublic, 0); - ClangASTContext::CompleteTagDeclarationDefinition(dispatch_tsd_indexes_s); - - ProcessStructReader struct_reader(m_process, m_dispatch_tsd_indexes_addr, - dispatch_tsd_indexes_s); - - m_libdispatch_tsd_indexes.dti_version = - struct_reader.GetField<uint16_t>(ConstString("dti_version")); - m_libdispatch_tsd_indexes.dti_queue_index = - struct_reader.GetField<uint16_t>(ConstString("dti_queue_index")); - m_libdispatch_tsd_indexes.dti_voucher_index = - struct_reader.GetField<uint16_t>(ConstString("dti_voucher_index")); - m_libdispatch_tsd_indexes.dti_qos_class_index = - struct_reader.GetField<uint16_t>(ConstString("dti_qos_class_index")); - } - } -} - -ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread, - ConstString type) { - ThreadSP originating_thread_sp; - if (BacktraceRecordingHeadersInitialized() && - type == ConstString("libdispatch")) { - Status error; - - // real_thread is either an actual, live thread (in which case we need to - // call into libBacktraceRecording to find its originator) or it is an - // extended backtrace itself, in which case we get the token from it and - // call into libBacktraceRecording to find the originator of that token. - - if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) { - originating_thread_sp = GetExtendedBacktraceFromItemRef( - real_thread->GetExtendedBacktraceToken()); - } else { - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret = - m_get_thread_item_info_handler.GetThreadItemInfo( - *cur_thread_sp.get(), real_thread->GetID(), m_page_to_free, - m_page_to_free_size, error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && - ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - bool stop_id_is_valid = true; - if (item.stop_id == 0) - stop_id_is_valid = false; - originating_thread_sp.reset(new HistoryThread( - *m_process, item.enqueuing_thread_id, item.enqueuing_callstack, - item.stop_id, stop_id_is_valid)); - originating_thread_sp->SetExtendedBacktraceToken( - item.item_that_enqueued_this); - originating_thread_sp->SetQueueName( - item.enqueuing_queue_label.c_str()); - originating_thread_sp->SetQueueID(item.enqueuing_queue_serialnum); - // originating_thread_sp->SetThreadName - // (item.enqueuing_thread_label.c_str()); - } - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } - } - } - return originating_thread_sp; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref) { - ThreadSP return_thread_sp; - - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - bool stop_id_is_valid = true; - if (item.stop_id == 0) - stop_id_is_valid = false; - return_thread_sp.reset(new HistoryThread( - *m_process, item.enqueuing_thread_id, item.enqueuing_callstack, - item.stop_id, stop_id_is_valid)); - return_thread_sp->SetExtendedBacktraceToken(item.item_that_enqueued_this); - return_thread_sp->SetQueueName(item.enqueuing_queue_label.c_str()); - return_thread_sp->SetQueueID(item.enqueuing_queue_serialnum); - // return_thread_sp->SetThreadName - // (item.enqueuing_thread_label.c_str()); - - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } - } - return return_thread_sp; -} - -ThreadSP -SystemRuntimeMacOSX::GetExtendedBacktraceForQueueItem(QueueItemSP queue_item_sp, - ConstString type) { - ThreadSP extended_thread_sp; - if (type != ConstString("libdispatch")) - return extended_thread_sp; - - bool stop_id_is_valid = true; - if (queue_item_sp->GetStopID() == 0) - stop_id_is_valid = false; - - extended_thread_sp.reset( - new HistoryThread(*m_process, queue_item_sp->GetEnqueueingThreadID(), - queue_item_sp->GetEnqueueingBacktrace(), - queue_item_sp->GetStopID(), stop_id_is_valid)); - extended_thread_sp->SetExtendedBacktraceToken( - queue_item_sp->GetItemThatEnqueuedThis()); - extended_thread_sp->SetQueueName(queue_item_sp->GetQueueLabel().c_str()); - extended_thread_sp->SetQueueID(queue_item_sp->GetEnqueueingQueueID()); - // extended_thread_sp->SetThreadName - // (queue_item_sp->GetThreadLabel().c_str()); - - return extended_thread_sp; -} - -/* Returns true if we were able to get the version / offset information - * out of libBacktraceRecording. false means we were unable to retrieve - * this; the queue_info_version field will be 0. - */ - -bool SystemRuntimeMacOSX::BacktraceRecordingHeadersInitialized() { - if (m_lib_backtrace_recording_info.queue_info_version != 0) - return true; - - addr_t queue_info_version_address = LLDB_INVALID_ADDRESS; - addr_t queue_info_data_offset_address = LLDB_INVALID_ADDRESS; - addr_t item_info_version_address = LLDB_INVALID_ADDRESS; - addr_t item_info_data_offset_address = LLDB_INVALID_ADDRESS; - Target &target = m_process->GetTarget(); - - static ConstString introspection_dispatch_queue_info_version( - "__introspection_dispatch_queue_info_version"); - SymbolContextList sc_list; - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_queue_info_data_offset( - "__introspection_dispatch_queue_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_queue_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - queue_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_version( - "__introspection_dispatch_item_info_version"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_version, eSymbolTypeData, sc_list) > - 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_version_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - sc_list.Clear(); - - static ConstString introspection_dispatch_item_info_data_offset( - "__introspection_dispatch_item_info_data_offset"); - if (m_process->GetTarget().GetImages().FindSymbolsWithNameAndType( - introspection_dispatch_item_info_data_offset, eSymbolTypeData, - sc_list) > 0) { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - AddressRange addr_range; - sc.GetAddressRange(eSymbolContextSymbol, 0, false, addr_range); - item_info_data_offset_address = - addr_range.GetBaseAddress().GetLoadAddress(&target); - } - - if (queue_info_version_address != LLDB_INVALID_ADDRESS && - queue_info_data_offset_address != LLDB_INVALID_ADDRESS && - item_info_version_address != LLDB_INVALID_ADDRESS && - item_info_data_offset_address != LLDB_INVALID_ADDRESS) { - Status error; - m_lib_backtrace_recording_info.queue_info_version = - m_process->ReadUnsignedIntegerFromMemory(queue_info_version_address, 2, - 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.queue_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - queue_info_data_offset_address, 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_version = - m_process->ReadUnsignedIntegerFromMemory(item_info_version_address, - 2, 0, error); - if (error.Success()) { - m_lib_backtrace_recording_info.item_info_data_offset = - m_process->ReadUnsignedIntegerFromMemory( - item_info_data_offset_address, 2, 0, error); - if (!error.Success()) { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } else { - m_lib_backtrace_recording_info.queue_info_version = 0; - } - } - } - - return m_lib_backtrace_recording_info.queue_info_version != 0; -} - -const std::vector<ConstString> & -SystemRuntimeMacOSX::GetExtendedBacktraceTypes() { - if (m_types.size() == 0) { - m_types.push_back(ConstString("libdispatch")); - // We could have pthread as another type in the future if we have a way of - // gathering that information & it's useful to distinguish between them. - } - return m_types; -} - -void SystemRuntimeMacOSX::PopulateQueueList( - lldb_private::QueueList &queue_list) { - if (BacktraceRecordingHeadersInitialized()) { - AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - queue_info_pointer = m_get_queues_handler.GetCurrentQueues( - *cur_thread_sp.get(), m_page_to_free, m_page_to_free_size, error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - - if (queue_info_pointer.count > 0 && - queue_info_pointer.queues_buffer_size > 0 && - queue_info_pointer.queues_buffer_ptr != 0 && - queue_info_pointer.queues_buffer_ptr != LLDB_INVALID_ADDRESS) { - PopulateQueuesUsingLibBTR(queue_info_pointer.queues_buffer_ptr, - queue_info_pointer.queues_buffer_size, - queue_info_pointer.count, queue_list); - } - } - } - } - - // We either didn't have libBacktraceRecording (and need to create the queues - // list based on threads) or we did get the queues list from - // libBacktraceRecording but some special queues may not be included in its - // information. This is needed because libBacktraceRecording will only list - // queues with pending or running items by default - but the magic com.apple - // .main-thread queue on thread 1 is always around. - - for (ThreadSP thread_sp : m_process->Threads()) { - if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) { - if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID) { - if (queue_list.FindQueueByID(thread_sp->GetQueueID()).get() == NULL) { - QueueSP queue_sp(new Queue(m_process->shared_from_this(), - thread_sp->GetQueueID(), - thread_sp->GetQueueName())); - if (thread_sp->ThreadHasQueueInformation()) { - queue_sp->SetKind(thread_sp->GetQueueKind()); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } else { - queue_sp->SetKind( - GetQueueKind(thread_sp->GetQueueLibdispatchQueueAddress())); - queue_sp->SetLibdispatchQueueAddress( - thread_sp->GetQueueLibdispatchQueueAddress()); - queue_list.AddQueue(queue_sp); - } - } - } - } - } -} - -// Returns either an array of introspection_dispatch_item_info_ref's for the -// pending items on a queue or an array introspection_dispatch_item_info_ref's -// and code addresses for the pending items on a queue. The information about -// each of these pending items then needs to be fetched individually by passing -// the ref to libBacktraceRecording. - -SystemRuntimeMacOSX::PendingItemsForQueue -SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) { - PendingItemsForQueue pending_item_refs; - AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer; - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - if (cur_thread_sp) { - Status error; - pending_items_pointer = m_get_pending_items_handler.GetPendingItems( - *cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (error.Success()) { - if (pending_items_pointer.count > 0 && - pending_items_pointer.items_buffer_size > 0 && - pending_items_pointer.items_buffer_ptr != 0 && - pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) { - DataBufferHeap data(pending_items_pointer.items_buffer_size, 0); - if (m_process->ReadMemory( - pending_items_pointer.items_buffer_ptr, data.GetBytes(), - pending_items_pointer.items_buffer_size, error)) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - - // We either have an array of - // void* item_ref - // (old style) or we have a structure returned which looks like - // - // struct introspection_dispatch_pending_item_info_s { - // void *item_ref; - // void *function_or_block; - // }; - // - // struct introspection_dispatch_pending_items_array_s { - // uint32_t version; - // uint32_t size_of_item_info; - // introspection_dispatch_pending_item_info_s items[]; - // } - - offset_t offset = 0; - int i = 0; - uint32_t version = extractor.GetU32(&offset); - if (version == 1) { - pending_item_refs.new_style = true; - uint32_t item_size = extractor.GetU32(&offset); - uint32_t start_of_array_offset = offset; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - offset = start_of_array_offset + (i * item_size); - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = extractor.GetPointer(&offset); - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } else { - offset = 0; - pending_item_refs.new_style = false; - while (offset < pending_items_pointer.items_buffer_size && - static_cast<size_t>(i) < pending_items_pointer.count) { - ItemRefAndCodeAddress item; - item.item_ref = extractor.GetPointer(&offset); - item.code_address = LLDB_INVALID_ADDRESS; - pending_item_refs.item_refs_and_code_addresses.push_back(item); - i++; - } - } - } - m_page_to_free = pending_items_pointer.items_buffer_ptr; - m_page_to_free_size = pending_items_pointer.items_buffer_size; - } - } - } - return pending_item_refs; -} - -void SystemRuntimeMacOSX::PopulatePendingItemsForQueue(Queue *queue) { - if (BacktraceRecordingHeadersInitialized()) { - PendingItemsForQueue pending_item_refs = - GetPendingItemRefsForQueue(queue->GetLibdispatchQueueAddress()); - for (ItemRefAndCodeAddress pending_item : - pending_item_refs.item_refs_and_code_addresses) { - Address addr; - m_process->GetTarget().ResolveLoadAddress(pending_item.code_address, - addr); - QueueItemSP queue_item_sp(new QueueItem(queue->shared_from_this(), - m_process->shared_from_this(), - pending_item.item_ref, addr)); - queue->PushPendingQueueItem(queue_item_sp); - } - } -} - -void SystemRuntimeMacOSX::CompleteQueueItem(QueueItem *queue_item, - addr_t item_ref) { - AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - - ThreadSP cur_thread_sp( - m_process->GetThreadList().GetExpressionExecutionThread()); - Status error; - ret = m_get_item_info_handler.GetItemInfo(*cur_thread_sp.get(), item_ref, - m_page_to_free, m_page_to_free_size, - error); - m_page_to_free = LLDB_INVALID_ADDRESS; - m_page_to_free_size = 0; - if (ret.item_buffer_ptr != 0 && ret.item_buffer_ptr != LLDB_INVALID_ADDRESS && - ret.item_buffer_size > 0) { - DataBufferHeap data(ret.item_buffer_size, 0); - if (m_process->ReadMemory(ret.item_buffer_ptr, data.GetBytes(), - ret.item_buffer_size, error) && - error.Success()) { - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - ItemInfo item = ExtractItemInfoFromBuffer(extractor); - queue_item->SetItemThatEnqueuedThis(item.item_that_enqueued_this); - queue_item->SetEnqueueingThreadID(item.enqueuing_thread_id); - queue_item->SetEnqueueingQueueID(item.enqueuing_queue_serialnum); - queue_item->SetStopID(item.stop_id); - queue_item->SetEnqueueingBacktrace(item.enqueuing_callstack); - queue_item->SetThreadLabel(item.enqueuing_thread_label); - queue_item->SetQueueLabel(item.enqueuing_queue_label); - queue_item->SetTargetQueueLabel(item.target_queue_label); - } - m_page_to_free = ret.item_buffer_ptr; - m_page_to_free_size = ret.item_buffer_size; - } -} - -void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR( - lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count, - lldb_private::QueueList &queue_list) { - Status error; - DataBufferHeap data(queues_buffer_size, 0); - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); - if (m_process->ReadMemory(queues_buffer, data.GetBytes(), queues_buffer_size, - error) == queues_buffer_size && - error.Success()) { - // We've read the information out of inferior memory; free it on the next - // call we make - m_page_to_free = queues_buffer; - m_page_to_free_size = queues_buffer_size; - - DataExtractor extractor(data.GetBytes(), data.GetByteSize(), - m_process->GetByteOrder(), - m_process->GetAddressByteSize()); - offset_t offset = 0; - uint64_t queues_read = 0; - - // The information about the queues is stored in this format (v1): typedef - // struct introspection_dispatch_queue_info_s { - // uint32_t offset_to_next; - // dispatch_queue_t queue; - // uint64_t serialnum; // queue's serialnum in the process, as - // provided by libdispatch - // uint32_t running_work_items_count; - // uint32_t pending_work_items_count; - // - // char data[]; // Starting here, we have variable-length data: - // // char queue_label[]; - // } introspection_dispatch_queue_info_s; - - while (queues_read < count && offset < queues_buffer_size) { - offset_t start_of_this_item = offset; - - uint32_t offset_to_next = extractor.GetU32(&offset); - - offset += 4; // Skip over the 4 bytes of reserved space - addr_t queue = extractor.GetPointer(&offset); - uint64_t serialnum = extractor.GetU64(&offset); - uint32_t running_work_items_count = extractor.GetU32(&offset); - uint32_t pending_work_items_count = extractor.GetU32(&offset); - - // Read the first field of the variable length data - offset = start_of_this_item + - m_lib_backtrace_recording_info.queue_info_data_offset; - const char *queue_label = extractor.GetCStr(&offset); - if (queue_label == NULL) - queue_label = ""; - - offset_t start_of_next_item = start_of_this_item + offset_to_next; - offset = start_of_next_item; - - if (log) - log->Printf("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added " - "queue with dispatch_queue_t 0x%" PRIx64 - ", serial number 0x%" PRIx64 - ", running items %d, pending items %d, name '%s'", - queue, serialnum, running_work_items_count, - pending_work_items_count, queue_label); - - QueueSP queue_sp( - new Queue(m_process->shared_from_this(), serialnum, queue_label)); - queue_sp->SetNumRunningWorkItems(running_work_items_count); - queue_sp->SetNumPendingWorkItems(pending_work_items_count); - queue_sp->SetLibdispatchQueueAddress(queue); - queue_sp->SetKind(GetQueueKind(queue)); - queue_list.AddQueue(queue_sp); - queues_read++; - } - } -} - -SystemRuntimeMacOSX::ItemInfo SystemRuntimeMacOSX::ExtractItemInfoFromBuffer( - lldb_private::DataExtractor &extractor) { - ItemInfo item; - - offset_t offset = 0; - - item.item_that_enqueued_this = extractor.GetPointer(&offset); - item.function_or_block = extractor.GetPointer(&offset); - item.enqueuing_thread_id = extractor.GetU64(&offset); - item.enqueuing_queue_serialnum = extractor.GetU64(&offset); - item.target_queue_serialnum = extractor.GetU64(&offset); - item.enqueuing_callstack_frame_count = extractor.GetU32(&offset); - item.stop_id = extractor.GetU32(&offset); - - offset = m_lib_backtrace_recording_info.item_info_data_offset; - - for (uint32_t i = 0; i < item.enqueuing_callstack_frame_count; i++) { - item.enqueuing_callstack.push_back(extractor.GetPointer(&offset)); - } - item.enqueuing_thread_label = extractor.GetCStr(&offset); - item.enqueuing_queue_label = extractor.GetCStr(&offset); - item.target_queue_label = extractor.GetCStr(&offset); - - return item; -} - -void SystemRuntimeMacOSX::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); -} - -void SystemRuntimeMacOSX::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); -} - -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginNameStatic() { - static ConstString g_name("systemruntime-macosx"); - return g_name; -} - -const char *SystemRuntimeMacOSX::GetPluginDescriptionStatic() { - return "System runtime plugin for Mac OS X native libraries."; -} - -//------------------------------------------------------------------ -// PluginInterface protocol -//------------------------------------------------------------------ -lldb_private::ConstString SystemRuntimeMacOSX::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t SystemRuntimeMacOSX::GetPluginVersion() { return 1; } diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h deleted file mode 100644 index 5fa78cee46406..0000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h +++ /dev/null @@ -1,299 +0,0 @@ -//===-- SystemRuntimeMacOSX.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_SystemRuntimeMacOSX_h_ -#define liblldb_SystemRuntimeMacOSX_h_ - -#include <mutex> -#include <string> -#include <vector> - -// Other libraries and framework include -#include "lldb/Core/ModuleList.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/QueueItem.h" -#include "lldb/Target/SystemRuntime.h" -#include "lldb/Utility/ConstString.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/UUID.h" - -#include "AppleGetItemInfoHandler.h" -#include "AppleGetPendingItemsHandler.h" -#include "AppleGetQueuesHandler.h" -#include "AppleGetThreadItemInfoHandler.h" - -class SystemRuntimeMacOSX : public lldb_private::SystemRuntime { -public: - SystemRuntimeMacOSX(lldb_private::Process *process); - - ~SystemRuntimeMacOSX() override; - - //------------------------------------------------------------------ - // Static Functions - //------------------------------------------------------------------ - static void Initialize(); - - static void Terminate(); - - static lldb_private::ConstString GetPluginNameStatic(); - - static const char *GetPluginDescriptionStatic(); - - static lldb_private::SystemRuntime * - CreateInstance(lldb_private::Process *process); - - //------------------------------------------------------------------ - // instance methods - //------------------------------------------------------------------ - - void Clear(bool clear_process); - - void Detach() override; - - const std::vector<lldb_private::ConstString> & - GetExtendedBacktraceTypes() override; - - lldb::ThreadSP - GetExtendedBacktraceThread(lldb::ThreadSP thread, - lldb_private::ConstString type) override; - - lldb::ThreadSP - GetExtendedBacktraceForQueueItem(lldb::QueueItemSP queue_item_sp, - lldb_private::ConstString type) override; - - lldb::ThreadSP GetExtendedBacktraceFromItemRef(lldb::addr_t item_ref); - - void PopulateQueueList(lldb_private::QueueList &queue_list) override; - - void PopulateQueuesUsingLibBTR(lldb::addr_t queues_buffer, - uint64_t queues_buffer_size, uint64_t count, - lldb_private::QueueList &queue_list); - - void PopulatePendingQueuesUsingLibBTR(lldb::addr_t items_buffer, - uint64_t items_buffer_size, - uint64_t count, - lldb_private::Queue *queue); - - std::string - GetQueueNameFromThreadQAddress(lldb::addr_t dispatch_qaddr) override; - - lldb::queue_id_t - GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) override; - - lldb::addr_t GetLibdispatchQueueAddressFromThreadQAddress( - lldb::addr_t dispatch_qaddr) override; - - void PopulatePendingItemsForQueue(lldb_private::Queue *queue) override; - - void CompleteQueueItem(lldb_private::QueueItem *queue_item, - lldb::addr_t item_ref) override; - - lldb::QueueKind GetQueueKind(lldb::addr_t dispatch_queue_addr) override; - - void AddThreadExtendedInfoPacketHints( - lldb_private::StructuredData::ObjectSP dict) override; - - bool SafeToCallFunctionsOnThisThread(lldb::ThreadSP thread_sp) override; - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; - - uint32_t GetPluginVersion() override; - -protected: - lldb::user_id_t m_break_id; - mutable std::recursive_mutex m_mutex; - -private: - struct libBacktraceRecording_info { - uint16_t queue_info_version; - uint16_t queue_info_data_offset; - uint16_t item_info_version; - uint16_t item_info_data_offset; - - libBacktraceRecording_info() - : queue_info_version(0), queue_info_data_offset(0), - item_info_version(0), item_info_data_offset(0) {} - }; - - // A structure which reflects the data recorded in the - // libBacktraceRecording introspection_dispatch_item_info_s. - struct ItemInfo { - lldb::addr_t item_that_enqueued_this; - lldb::addr_t function_or_block; - uint64_t enqueuing_thread_id; - uint64_t enqueuing_queue_serialnum; - uint64_t target_queue_serialnum; - uint32_t enqueuing_callstack_frame_count; - uint32_t stop_id; - std::vector<lldb::addr_t> enqueuing_callstack; - std::string enqueuing_thread_label; - std::string enqueuing_queue_label; - std::string target_queue_label; - }; - - // The offsets of different fields of the dispatch_queue_t structure in - // a thread/queue process. - // Based on libdispatch src/queue_private.h, struct dispatch_queue_offsets_s - // With dqo_version 1-3, the dqo_label field is a per-queue value and cannot - // be cached. - // With dqo_version 4 (Mac OS X 10.9 / iOS 7), dqo_label is a constant value - // that can be cached. - struct LibdispatchOffsets { - uint16_t dqo_version; - uint16_t dqo_label; - uint16_t dqo_label_size; - uint16_t dqo_flags; - uint16_t dqo_flags_size; - uint16_t dqo_serialnum; - uint16_t dqo_serialnum_size; - uint16_t dqo_width; - uint16_t dqo_width_size; - uint16_t dqo_running; - uint16_t dqo_running_size; - - uint16_t dqo_suspend_cnt; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_suspend_cnt_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t dqo_target_queue; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - uint16_t dqo_target_queue_size; // version 5 and later, starting with Mac OS - // X 10.10/iOS 8 - uint16_t - dqo_priority; // version 5 and later, starting with Mac OS X 10.10/iOS 8 - uint16_t dqo_priority_size; // version 5 and later, starting with Mac OS X - // 10.10/iOS 8 - - LibdispatchOffsets() { - dqo_version = UINT16_MAX; - dqo_flags = UINT16_MAX; - dqo_serialnum = UINT16_MAX; - dqo_label = UINT16_MAX; - dqo_width = UINT16_MAX; - dqo_running = UINT16_MAX; - dqo_suspend_cnt = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_target_queue = UINT16_MAX; - dqo_priority = UINT16_MAX; - } - - bool IsValid() { return dqo_version != UINT16_MAX; } - - bool LabelIsValid() { return dqo_label != UINT16_MAX; } - }; - - struct LibdispatchVoucherOffsets { - uint16_t vo_version; - uint16_t vo_activity_ids_count; - uint16_t vo_activity_ids_count_size; - uint16_t vo_activity_ids_array; - uint16_t vo_activity_ids_array_entry_size; - - LibdispatchVoucherOffsets() - : vo_version(UINT16_MAX), vo_activity_ids_count(UINT16_MAX), - vo_activity_ids_count_size(UINT16_MAX), - vo_activity_ids_array(UINT16_MAX), - vo_activity_ids_array_entry_size(UINT16_MAX) {} - - bool IsValid() { return vo_version != UINT16_MAX; } - }; - - struct LibdispatchTSDIndexes { - uint16_t dti_version; - uint64_t dti_queue_index; - uint64_t dti_voucher_index; - uint64_t dti_qos_class_index; - - LibdispatchTSDIndexes() - : dti_version(UINT16_MAX), dti_queue_index(UINT64_MAX), - dti_voucher_index(UINT64_MAX), dti_qos_class_index(UINT64_MAX) {} - - bool IsValid() { return dti_version != UINT16_MAX; } - }; - - struct LibpthreadOffsets { - uint16_t plo_version; - uint16_t plo_pthread_tsd_base_offset; - uint16_t plo_pthread_tsd_base_address_offset; - uint16_t plo_pthread_tsd_entry_size; - - LibpthreadOffsets() - : plo_version(UINT16_MAX), plo_pthread_tsd_base_offset(UINT16_MAX), - plo_pthread_tsd_base_address_offset(UINT16_MAX), - plo_pthread_tsd_entry_size(UINT16_MAX) {} - - bool IsValid() { return plo_version != UINT16_MAX; } - }; - - // The libBacktraceRecording function - // __introspection_dispatch_queue_get_pending_items has - // two forms. It can either return a simple array of item_refs (void *) size - // or it can return - // a header with uint32_t version, a uint32_t size of item, and then an array - // of item_refs (void*) - // and code addresses (void*) for all the pending blocks. - - struct ItemRefAndCodeAddress { - lldb::addr_t item_ref; - lldb::addr_t code_address; - }; - - struct PendingItemsForQueue { - bool new_style; // new-style means both item_refs and code_addresses avail - // old-style means only item_refs is filled in - std::vector<ItemRefAndCodeAddress> item_refs_and_code_addresses; - }; - - bool BacktraceRecordingHeadersInitialized(); - - void ReadLibdispatchOffsetsAddress(); - - void ReadLibdispatchOffsets(); - - void ReadLibpthreadOffsetsAddress(); - - void ReadLibpthreadOffsets(); - - void ReadLibdispatchTSDIndexesAddress(); - - void ReadLibdispatchTSDIndexes(); - - PendingItemsForQueue GetPendingItemRefsForQueue(lldb::addr_t queue); - - ItemInfo ExtractItemInfoFromBuffer(lldb_private::DataExtractor &extractor); - - lldb_private::AppleGetQueuesHandler m_get_queues_handler; - lldb_private::AppleGetPendingItemsHandler m_get_pending_items_handler; - lldb_private::AppleGetItemInfoHandler m_get_item_info_handler; - lldb_private::AppleGetThreadItemInfoHandler m_get_thread_item_info_handler; - - lldb::addr_t m_page_to_free; - uint64_t m_page_to_free_size; - libBacktraceRecording_info m_lib_backtrace_recording_info; - - lldb::addr_t m_dispatch_queue_offsets_addr; - struct LibdispatchOffsets m_libdispatch_offsets; - - lldb::addr_t m_libpthread_layout_offsets_addr; - struct LibpthreadOffsets m_libpthread_offsets; - - lldb::addr_t m_dispatch_tsd_indexes_addr; - struct LibdispatchTSDIndexes m_libdispatch_tsd_indexes; - - lldb::addr_t m_dispatch_voucher_offsets_addr; - struct LibdispatchVoucherOffsets m_libdispatch_voucher_offsets; - - DISALLOW_COPY_AND_ASSIGN(SystemRuntimeMacOSX); -}; - -#endif // liblldb_SystemRuntimeMacOSX_h_ diff --git a/source/Plugins/UnwindAssembly/CMakeLists.txt b/source/Plugins/UnwindAssembly/CMakeLists.txt deleted file mode 100644 index 1723a06045804..0000000000000 --- a/source/Plugins/UnwindAssembly/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(InstEmulation) -add_subdirectory(x86) diff --git a/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt b/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt deleted file mode 100644 index 7b7fd721f8505..0000000000000 --- a/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_lldb_library(lldbPluginUnwindAssemblyInstEmulation PLUGIN - UnwindAssemblyInstEmulation.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - ) diff --git a/source/Plugins/UnwindAssembly/x86/CMakeLists.txt b/source/Plugins/UnwindAssembly/x86/CMakeLists.txt deleted file mode 100644 index 425ae11909923..0000000000000 --- a/source/Plugins/UnwindAssembly/x86/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_lldb_library(lldbPluginUnwindAssemblyX86 PLUGIN - UnwindAssembly-x86.cpp - x86AssemblyInspectionEngine.cpp - - LINK_LIBS - lldbCore - lldbSymbol - lldbTarget - lldbUtility - LINK_COMPONENTS - Support - MC - MCDisassembler - ) |