diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:12:36 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:12:36 +0000 |
commit | ef5d0b5e97ec8e6fa395d377b09aa7755e345b4f (patch) | |
tree | 27916256fdeeb57d10d2f3d6948be5d71a703215 /source/Plugins | |
parent | 76e0736e7fcfeb179779e49c05604464b1ccd704 (diff) | |
download | src-ef5d0b5e97ec8e6fa395d377b09aa7755e345b4f.tar.gz src-ef5d0b5e97ec8e6fa395d377b09aa7755e345b4f.zip |
Vendor import of lldb trunk r321017:vendor/lldb/lldb-trunk-r321017
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=326949
svn path=/vendor/lldb/lldb-trunk-r321017/; revision=326950; tag=vendor/lldb/lldb-trunk-r321017
Diffstat (limited to 'source/Plugins')
227 files changed, 6581 insertions, 2958 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index fd5ee6ede4c3..1bd1c1bf8dd4 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -1413,10 +1413,6 @@ bool ABIMacOSX_arm::PrepareTrivialCall(Thread &thread, addr_t sp, if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_num, return_addr)) return false; - // Set "sp" to the requested value - if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) - return false; - // If bit zero or 1 is set, this must be a thumb function, no need to figure // this out from the symbols. so_addr.SetLoadAddress(function_addr, target_sp.get()); @@ -1441,6 +1437,11 @@ bool ABIMacOSX_arm::PrepareTrivialCall(Thread &thread, addr_t sp, function_addr &= ~1ull; // clear bit zero since the CPSR will take care of the mode for us + // Update the sp - stack pointer - to be aligned to 16-bytes + sp &= ~(0xfull); + if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) + return false; + // Set "pc" to the address requested if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, function_addr)) return false; diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index f91ed851a3e5..dbe333c4649e 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -2018,7 +2018,7 @@ bool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) { if (name[0] == 'l' && name[1] == 'r') // lr return false; - if (name[0] == 'x') { + if (name[0] == 'x' || name[0] == 'r') { // Volatile registers: x0-x18 // Although documentation says only x19-28 + sp are callee saved // We ll also have to treat x30 as non-volatile. diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 63da5a77b48f..d799c587dd07 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -205,11 +205,12 @@ ABISysV_i386::GetRegisterInfoArray(uint32_t &count) { ABISP ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { static ABISP g_abi_sp; - if ((arch.GetTriple().getArch() == llvm::Triple::x86) && - arch.GetTriple().isOSLinux()) { - if (!g_abi_sp) - g_abi_sp.reset(new ABISysV_i386(process_sp)); - return g_abi_sp; + if (arch.GetTriple().getVendor() != llvm::Triple::Apple) { + if (arch.GetTriple().getArch() == llvm::Triple::x86) { + if (!g_abi_sp) + g_abi_sp.reset(new ABISysV_i386(process_sp)); + return g_abi_sp; + } } return ABISP(); } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index 06a8ce932fda..2fee176739f3 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -291,47 +291,6 @@ bool ABISysV_ppc::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index c090f01ccb1c..0348853c7fa0 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -291,47 +291,6 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, RegisterValue reg_value; -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 10bbae566491..41d146f24526 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -13,6 +13,7 @@ // C++ Includes // Other libraries and framework includes #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" // Project includes @@ -1160,48 +1161,6 @@ bool ABISysV_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp, ProcessSP process_sp(thread.GetProcess()); RegisterValue reg_value; - -#if 0 - // This code adds an extra frame so that we don't lose the function that we came from - // by pushing the PC and the FP and then writing the current FP to point to the FP value - // we just pushed. It is disabled for now until the stack backtracing code can be debugged. - - // Save current PC - const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - - sp -= 8; - - // Save current FP - if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) - { - if (log) - log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); - - if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) - return false; - } - // Setup FP backchain - reg_value.SetUInt64 (sp); - - if (log) - log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); - - if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) - { - return false; - } - - sp -= 8; - } -#endif - if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, @@ -1908,52 +1867,16 @@ bool ABISysV_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) { // It's being revised & updated at https://github.com/hjl-tools/x86-psABI/ bool ABISysV_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { - if (reg_info) { - // Preserved registers are : - // rbx, rsp, rbp, r12, r13, r14, r15 - // mxcsr (partially preserved) - // x87 control word - - const char *name = reg_info->name; - if (name[0] == 'r') { - switch (name[1]) { - case '1': // r12, r13, r14, r15 - if (name[2] >= '2' && name[2] <= '5') - return name[3] == '\0'; - break; - - default: - break; - } - } - - // Accept shorter-variant versions, rbx/ebx, rip/ eip, etc. - if (name[0] == 'r' || name[0] == 'e') { - switch (name[1]) { - case 'b': // rbp, rbx - if (name[2] == 'p' || name[2] == 'x') - return name[3] == '\0'; - break; - - case 'i': // rip - if (name[2] == 'p') - return name[3] == '\0'; - break; - - case 's': // rsp - if (name[2] == 'p') - return name[3] == '\0'; - break; - } - } - if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp - return true; - if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp - return true; - if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc - return true; - } - return false; + if (!reg_info) + return false; + assert(reg_info->name != nullptr && "unnamed register?"); + std::string Name = std::string(reg_info->name); + bool IsCalleeSaved = + llvm::StringSwitch<bool>(Name) + .Cases("r12", "r13", "r14", "r15", "rbp", "ebp", "rbx", "ebx", true) + .Cases("rip", "eip", "rsp", "esp", "sp", "fp", "pc", true) + .Default(false); + return IsCalleeSaved; } void ABISysV_x86_64::Initialize() { diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp new file mode 100644 index 000000000000..abac6d3001af --- /dev/null +++ b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp @@ -0,0 +1,131 @@ +//===-- ArchitectureArm.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/Architecture/Arm/ArchitectureArm.h" +#include "Plugins/Process/Utility/ARMDefines.h" +#include "Plugins/Process/Utility/InstructionUtils.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" + +using namespace lldb_private; +using namespace lldb; + +ConstString ArchitectureArm::GetPluginNameStatic() { + return ConstString("arm"); +} + +void ArchitectureArm::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "Arm-specific algorithms", + &ArchitectureArm::Create); +} + +void ArchitectureArm::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureArm::Create); +} + +std::unique_ptr<Architecture> ArchitectureArm::Create(const ArchSpec &arch) { + if (arch.GetMachine() != llvm::Triple::arm) + return nullptr; + return std::unique_ptr<Architecture>(new ArchitectureArm()); +} + +ConstString ArchitectureArm::GetPluginName() { return GetPluginNameStatic(); } +uint32_t ArchitectureArm::GetPluginVersion() { return 1; } + +void ArchitectureArm::OverrideStopInfo(Thread &thread) { + // We need to check if we are stopped in Thumb mode in a IT instruction + // and detect if the condition doesn't pass. If this is the case it means + // we won't actually execute this instruction. If this happens we need to + // clear the stop reason to no thread plans think we are stopped for a + // reason and the plans should keep going. + // + // We do this because when single stepping many ARM processes, debuggers + // often use the BVR/BCR registers that says "stop when the PC is not + // equal to its current value". This method of stepping means we can end + // up stopping on instructions inside an if/then block that wouldn't get + // executed. By fixing this we can stop the debugger from seeming like + // you stepped through both the "if" _and_ the "else" clause when source + // level stepping because the debugger stops regardless due to the BVR/BCR + // triggering a stop. + // + // It also means we can set breakpoints on instructions inside an an + // if/then block and correctly skip them if we use the BKPT instruction. + // The ARM and Thumb BKPT instructions are unconditional even when executed + // in a Thumb IT block. + // + // If your debugger inserts software traps in ARM/Thumb code, it will + // need to use 16 and 32 bit instruction for 16 and 32 bit thumb + // instructions respectively. If your debugger inserts a 16 bit thumb + // trap on top of a 32 bit thumb instruction for an opcode that is inside + // an if/then, it will change the it/then to conditionally execute your + // 16 bit trap and then cause your program to crash if it executes the + // trailing 16 bits (the second half of the 32 bit thumb instruction you + // partially overwrote). + + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + if (!reg_ctx_sp) + return; + + const uint32_t cpsr = reg_ctx_sp->GetFlags(0); + if (cpsr == 0) + return; + + // Read the J and T bits to get the ISETSTATE + const uint32_t J = Bit32(cpsr, 24); + const uint32_t T = Bit32(cpsr, 5); + const uint32_t ISETSTATE = J << 1 | T; + if (ISETSTATE == 0) { +// NOTE: I am pretty sure we want to enable the code below +// that detects when we stop on an instruction in ARM mode +// that is conditional and the condition doesn't pass. This +// can happen if you set a breakpoint on an instruction that +// is conditional. We currently will _always_ stop on the +// instruction which is bad. You can also run into this while +// single stepping and you could appear to run code in the "if" +// and in the "else" clause because it would stop at all of the +// conditional instructions in both. +// In such cases, we really don't want to stop at this location. +// I will check with the lldb-dev list first before I enable this. +#if 0 + // ARM mode: check for condition on intsruction + const addr_t pc = reg_ctx_sp->GetPC(); + Status error; + // If we fail to read the opcode we will get UINT64_MAX as the + // result in "opcode" which we can use to detect if we read a + // valid opcode. + const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error); + if (opcode <= UINT32_MAX) + { + const uint32_t condition = Bits32((uint32_t)opcode, 31, 28); + if (!ARMConditionPassed(condition, cpsr)) + { + // We ARE stopped on an ARM instruction whose condition doesn't + // pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo (StopInfoSP()); + } + } +#endif + } else if (ISETSTATE == 1) { + // Thumb mode + const uint32_t ITSTATE = Bits32(cpsr, 15, 10) << 2 | Bits32(cpsr, 26, 25); + if (ITSTATE != 0) { + const uint32_t condition = Bits32(ITSTATE, 7, 4); + if (!ARMConditionPassed(condition, cpsr)) { + // We ARE stopped in a Thumb IT instruction on an instruction whose + // condition doesn't pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo(StopInfoSP()); + } + } + } +} diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.h b/source/Plugins/Architecture/Arm/ArchitectureArm.h new file mode 100644 index 000000000000..9ce6c69ef271 --- /dev/null +++ b/source/Plugins/Architecture/Arm/ArchitectureArm.h @@ -0,0 +1,35 @@ +//===-- ArchitectureArm.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_PLUGIN_ARCHITECTURE_ARM_H +#define LLDB_PLUGIN_ARCHITECTURE_ARM_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureArm : public Architecture { +public: + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + void OverrideStopInfo(Thread &thread) override; + +private: + static std::unique_ptr<Architecture> Create(const ArchSpec &arch); + ArchitectureArm() = default; +}; + +} // namespace lldb_private + +#endif // LLDB_PLUGIN_ARCHITECTURE_ARM_H diff --git a/source/Plugins/Architecture/Arm/CMakeLists.txt b/source/Plugins/Architecture/Arm/CMakeLists.txt new file mode 100644 index 000000000000..60bbe69a99fb --- /dev/null +++ b/source/Plugins/Architecture/Arm/CMakeLists.txt @@ -0,0 +1,11 @@ +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 new file mode 100644 index 000000000000..5abaa8e68231 --- /dev/null +++ b/source/Plugins/Architecture/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Arm) diff --git a/source/Plugins/CMakeLists.txt b/source/Plugins/CMakeLists.txt index ac1afcbc331e..5092b210a12c 100644 --- a/source/Plugins/CMakeLists.txt +++ b/source/Plugins/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(ABI) +add_subdirectory(Architecture) add_subdirectory(Disassembler) add_subdirectory(DynamicLoader) add_subdirectory(ExpressionParser) diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index a82b3fe267b3..a81a0306671e 100644 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -1229,6 +1229,16 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries( 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++; } @@ -1397,7 +1407,7 @@ bool DynamicLoaderDarwinKernel::ReadAllKextSummaries() { void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const { if (log == NULL) return; - const uint8_t *u = (uint8_t *)m_uuid.GetBytes(); + const uint8_t *u = static_cast<const uint8_t *>(m_uuid.GetBytes()); if (m_load_address == LLDB_INVALID_ADDRESS) { if (u) { diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 1ef1be5d0adb..c49cdc2f11b1 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index c1986976b0fc..e601d64f0d8d 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -18,6 +14,7 @@ #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index c381326ebf4f..6502d7a7a58c 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -11,8 +11,11 @@ #include "DynamicLoaderWindowsDYLD.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlanStepInstruction.h" #include "llvm/ADT/Triple.h" @@ -72,5 +75,44 @@ uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } ThreadPlanSP DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) { - return ThreadPlanSP(); + auto arch = m_process->GetTarget().GetArchitecture(); + if (arch.GetMachine() != llvm::Triple::x86) { + return ThreadPlanSP(); + } + + uint64_t pc = thread.GetRegisterContext()->GetPC(); + // Max size of an instruction in x86 is 15 bytes. + AddressRange range(pc, 2 * 15); + + ExecutionContext exe_ctx(m_process->GetTarget()); + DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( + arch, nullptr, nullptr, exe_ctx, range, true); + if (!disassembler_sp) { + return ThreadPlanSP(); + } + + InstructionList *insn_list = &disassembler_sp->GetInstructionList(); + if (insn_list == nullptr) { + return ThreadPlanSP(); + } + + // First instruction in a x86 Windows trampoline is going to be an indirect + // jump through the IAT and the next one will be a nop (usually there for + // alignment purposes). e.g.: + // 0x70ff4cfc <+956>: jmpl *0x7100c2a8 + // 0x70ff4d02 <+962>: nop + + auto first_insn = insn_list->GetInstructionAtIndex(0); + auto second_insn = insn_list->GetInstructionAtIndex(1); + + if (first_insn == nullptr || second_insn == nullptr || + strcmp(first_insn->GetMnemonic(&exe_ctx), "jmpl") != 0 || + strcmp(second_insn->GetMnemonic(&exe_ctx), "nop") != 0) { + return ThreadPlanSP(); + } + + assert(first_insn->DoesBranch() && !second_insn->DoesBranch()); + + return ThreadPlanSP(new ThreadPlanStepInstruction( + thread, false, false, eVoteNoOpinion, eVoteNoOpinion)); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 7622791778ba..7f031356b3c3 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -51,8 +51,94 @@ private: }; } +ClangASTSource::ClangASTSource(const lldb::TargetSP &target) + : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), + m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { + if (!target->GetUseModernTypeLookup()) { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } +} + +void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context, + clang::FileManager &file_manager, + bool is_shared_context) { + m_ast_context = &ast_context; + m_file_manager = &file_manager; + if (m_target->GetUseModernTypeLookup()) { + // Configure the ExternalASTMerger. The merger needs to be able to import + // types from any source that we would do lookups in, which includes the + // persistent AST context as well as the modules and Objective-C runtime + // AST contexts. + + lldbassert(!m_merger_up); + clang::ExternalASTMerger::ImporterTarget target = {ast_context, + file_manager}; + std::vector<clang::ExternalASTMerger::ImporterSource> sources; + for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) { + if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>( + module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC))) { + lldbassert(module_ast_ctx->getASTContext()); + lldbassert(module_ast_ctx->getFileManager()); + sources.push_back({*module_ast_ctx->getASTContext(), + *module_ast_ctx->getFileManager(), + module_ast_ctx->GetOriginMap() + }); + } + } + + do { + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *runtime_decl_vendor = language_runtime->GetDeclVendor(); + + if (!runtime_decl_vendor) + break; + + sources.push_back(runtime_decl_vendor->GetImporterSource()); + } while (0); + + do { + DeclVendor *modules_decl_vendor = + m_target->GetClangModulesDeclVendor(); + + if (!modules_decl_vendor) + break; + + sources.push_back(modules_decl_vendor->GetImporterSource()); + } while (0); + + if (!is_shared_context) { + // Update the scratch AST context's merger to reflect any new sources we + // might have come across since the last time an expression was parsed. + + auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + m_target->GetScratchClangASTContext()); + + scratch_ast_context->GetMergerUnchecked().AddSources(sources); + + sources.push_back({*scratch_ast_context->getASTContext(), + *scratch_ast_context->getFileManager(), + scratch_ast_context->GetOriginMap()}); + } while (0); + + m_merger_up = + llvm::make_unique<clang::ExternalASTMerger>(target, sources); + } else { + m_ast_importer_sp->InstallMapCompleter(&ast_context, *this); + } +} + ClangASTSource::~ClangASTSource() { - m_ast_importer_sp->ForgetDestination(m_ast_context); + if (m_ast_importer_sp) + m_ast_importer_sp->ForgetDestination(m_ast_context); // We are in the process of destruction, don't create clang ast context on // demand @@ -69,7 +155,7 @@ ClangASTSource::~ClangASTSource() { if (!scratch_ast_context) return; - if (m_ast_context != scratch_ast_context) + if (m_ast_context != scratch_ast_context && m_ast_importer_sp) m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); } @@ -203,6 +289,13 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { m_active_lexical_decls.insert(tag_decl); ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + if (!m_ast_importer_sp) { + if (HasMerger()) { + GetMergerUnchecked().CompleteType(tag_decl); + } + return; + } + if (!m_ast_importer_sp->CompleteTagDecl(tag_decl)) { // We couldn't complete the type. Maybe there's a definition // somewhere else that can be completed. @@ -337,6 +430,22 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { dumper.ToLog(log, " [COID] "); } + if (!m_ast_importer_sp) { + if (HasMerger()) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + + GetMergerUnchecked().CompleteType(interface_decl); + } else { + lldbassert(0 && "No mechanism for completing a type!"); + } + return; + } + Decl *original_decl = NULL; ASTContext *original_ctx = NULL; @@ -367,7 +476,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) { } clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( - clang::ObjCInterfaceDecl *interface_decl) { + const clang::ObjCInterfaceDecl *interface_decl) { lldb::ProcessSP process(m_target->GetProcessSP()); if (!process) @@ -411,6 +520,22 @@ void ClangASTSource::FindExternalLexicalDecls( const DeclContext *decl_context, llvm::function_ref<bool(Decl::Kind)> predicate, llvm::SmallVectorImpl<Decl *> &decls) { + + if (HasMerger()) { + if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + return GetMergerUnchecked().FindExternalLexicalDecls(decl_context, + predicate, + decls); + } else if (!m_ast_importer_sp) + return; + ClangASTMetrics::RegisterLexicalQuery(); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -507,8 +632,7 @@ void ClangASTSource::FindExternalLexicalDecls( decl->getDeclKindName(), ast_dumper.GetCString()); } - Decl *copied_decl = - m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + Decl *copied_decl = CopyDecl(decl); if (!copied_decl) continue; @@ -568,12 +692,31 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { name.GetCString(), context.m_decl_context->getDeclKindName()); } + if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context) + /* possibly handle NamespaceDecls here? */) { + if (auto *interface_decl = + dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != interface_decl)) { + GetMergerUnchecked().ForceRecordOrigin( + interface_decl, + {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + + GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, + context.m_decl_name); + return; // otherwise we may need to fall back + } + context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) { - ClangASTImporter::NamespaceMapSP namespace_map = - m_ast_importer_sp->GetNamespaceMap(namespace_context); + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp ? + m_ast_importer_sp->GetNamespaceMap(namespace_context) : nullptr; if (log && log->GetVerbose()) log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", @@ -593,7 +736,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { FindExternalVisibleDecls(context, i->first, i->second, current_id); } - } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) { + } else if (isa<ObjCInterfaceDecl>(context.m_decl_context) && !HasMerger()) { FindObjCPropertyAndIvarDecls(context); } else if (!isa<TranslationUnitDecl>(context.m_decl_context)) { // we shouldn't be getting FindExternalVisibleDecls calls for these @@ -623,6 +766,25 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) { } } +bool ClangASTSource::IgnoreName(const ConstString name, + bool ignore_all_dollar_names) { + static const ConstString id_name("id"); + static const ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return true; + + StringRef name_string_ref = name.GetStringRef(); + + // The ClangASTSource is not responsible for finding $-names. + if (name_string_ref.empty() || + (ignore_all_dollar_names && name_string_ref.startswith("$")) || + name_string_ref.startswith("_$")) + return true; + + return false; +} + void ClangASTSource::FindExternalVisibleDecls( NameSearchContext &context, lldb::ModuleSP module_sp, CompilerDeclContext &namespace_decl, unsigned int current_id) { @@ -633,20 +795,7 @@ void ClangASTSource::FindExternalVisibleDecls( SymbolContextList sc_list; const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) - return; - - if (name_unique_cstr == NULL) - return; - - // The ClangASTSource is not responsible for finding $-names. - if (name_unique_cstr[0] == '$') + if (IgnoreName(name, true)) return; if (module_sp && namespace_decl) { @@ -671,7 +820,7 @@ void ClangASTSource::FindExternalVisibleDecls( module_sp->GetFileSpec().GetFilename().GetCString()); } } - } else { + } else if (!HasMerger()) { const ModuleList &target_images = m_target->GetImages(); std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); @@ -774,9 +923,7 @@ void ClangASTSource::FindExternalVisibleDecls( if (llvm::isa<clang::TypeDecl>(decl_from_modules) || llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || llvm::isa<clang::EnumConstantDecl>(decl_from_modules)) { - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; @@ -831,8 +978,7 @@ void ClangASTSource::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::Decl *copied_decl = CopyDecl(decls[0]); clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; @@ -875,7 +1021,7 @@ public: DeclFromParser() : TaggedASTDecl<D>() {} DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromUser<D> GetOrigin(ClangASTImporter *importer); + DeclFromUser<D> GetOrigin(ClangASTSource &source); }; template <class D> class DeclFromUser : public TaggedASTDecl<D> { @@ -883,32 +1029,29 @@ public: DeclFromUser() : TaggedASTDecl<D>() {} DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) {} - DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); + DeclFromParser<D> Import(ClangASTSource &source); }; template <class D> -DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) { +DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) { DeclFromUser<> origin_decl; - importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + source.ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); if (origin_decl.IsInvalid()) return DeclFromUser<D>(); return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); } template <class D> -DeclFromParser<D> DeclFromUser<D>::Import(ClangASTImporter *importer, - ASTContext &dest_ctx) { - DeclFromParser<> parser_generic_decl( - importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); +DeclFromParser<D> DeclFromUser<D>::Import(ClangASTSource &source) { + DeclFromParser<> parser_generic_decl(source.CopyDecl(this->decl)); if (parser_generic_decl.IsInvalid()) return DeclFromParser<D>(); return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); } -static bool FindObjCMethodDeclsWithOrigin( +bool ClangASTSource::FindObjCMethodDeclsWithOrigin( unsigned int current_id, NameSearchContext &context, - ObjCInterfaceDecl *original_interface_decl, clang::ASTContext *ast_context, - ClangASTImporter *ast_importer, const char *log_info) { + ObjCInterfaceDecl *original_interface_decl, const char *log_info) { const DeclarationName &decl_name(context.m_decl_name); clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); @@ -967,8 +1110,7 @@ static bool FindObjCMethodDeclsWithOrigin( if (!result_method) continue; - Decl *copied_decl = ast_importer->CopyDecl( - ast_context, &result_method->getASTContext(), result_method); + Decl *copied_decl = CopyDecl(result_method); if (!copied_decl) continue; @@ -995,6 +1137,21 @@ static bool FindObjCMethodDeclsWithOrigin( void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + if (HasMerger()) { + if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) { + ObjCInterfaceDecl *complete_iface_decl = + GetCompleteObjCInterface(interface_decl); + + if (complete_iface_decl && (complete_iface_decl != context.m_decl_context)) { + m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()}); + } + } + + GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context, + context.m_decl_name); + return; + } + static unsigned int invocation_id = 0; unsigned int current_id = invocation_id++; @@ -1021,8 +1178,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { dyn_cast<ObjCInterfaceDecl>(original_decl); if (FindObjCMethodDeclsWithOrigin(current_id, context, - original_interface_decl, m_ast_context, - m_ast_importer_sp.get(), "at origin")) + original_interface_decl, "at origin")) return; // found it, no need to look any further } while (0); @@ -1160,8 +1316,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { continue; if (found_interface_decl->getName() == interface_decl->getName()) { - Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &method_decl->getASTContext(), method_decl); + Decl *copied_decl = CopyDecl(method_decl); if (!copied_decl) continue; @@ -1210,7 +1365,6 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { static_cast<void *>(&complete_iface_decl->getASTContext())); FindObjCMethodDeclsWithOrigin(current_id, context, complete_interface_decl, - m_ast_context, m_ast_importer_sp.get(), "in debug info"); return; @@ -1238,8 +1392,7 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { break; if (FindObjCMethodDeclsWithOrigin( - current_id, context, interface_decl_from_modules, m_ast_context, - m_ast_importer_sp.get(), "in modules")) + current_id, context, interface_decl_from_modules, "in modules")) return; } } while (0); @@ -1278,14 +1431,12 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { break; FindObjCMethodDeclsWithOrigin(current_id, context, runtime_interface_decl, - m_ast_context, m_ast_importer_sp.get(), "in runtime"); } while (0); } static bool FindObjCPropertyAndIvarDeclsWithOrigin( - unsigned int current_id, NameSearchContext &context, - clang::ASTContext &ast_context, ClangASTImporter *ast_importer, + unsigned int current_id, NameSearchContext &context, ClangASTSource &source, DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -1305,7 +1456,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (origin_property_decl.IsValid()) { DeclFromParser<ObjCPropertyDecl> parser_property_decl( - origin_property_decl.Import(ast_importer, ast_context)); + origin_property_decl.Import(source)); if (parser_property_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_property_decl.decl); @@ -1323,7 +1474,7 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin( if (origin_ivar_decl.IsValid()) { DeclFromParser<ObjCIvarDecl> parser_ivar_decl( - origin_ivar_decl.Import(ast_importer, ast_context)); + origin_ivar_decl.Import(source)); if (parser_ivar_decl.IsValid()) { if (log) { ASTDumper dumper((Decl *)parser_ivar_decl.decl); @@ -1348,7 +1499,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl( cast<ObjCInterfaceDecl>(context.m_decl_context)); DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl( - parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + parser_iface_decl.GetOrigin(*this)); ConstString class_name(parser_iface_decl->getNameAsString().c_str()); @@ -1360,8 +1511,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { context.m_decl_name.getAsString().c_str()); if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - origin_iface_decl)) + current_id, context, *this, origin_iface_decl)) return; if (log) @@ -1397,8 +1547,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<const void *>(complete_iface_decl.decl), static_cast<void *>(&complete_iface_decl->getASTContext())); - FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *m_ast_context, - m_ast_importer_sp.get(), + FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, complete_iface_decl); return; @@ -1435,9 +1584,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<const void *>(interface_decl_from_modules.decl), static_cast<void *>(&interface_decl_from_modules->getASTContext())); - if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - interface_decl_from_modules)) + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, context, *this, + interface_decl_from_modules)) return; } while (0); @@ -1483,8 +1631,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { static_cast<void *>(&interface_decl_from_runtime->getASTContext())); if (FindObjCPropertyAndIvarDeclsWithOrigin( - current_id, context, *m_ast_context, m_ast_importer_sp.get(), - interface_decl_from_runtime)) + current_id, context, *this, interface_decl_from_runtime)) return; } while (0); } @@ -1495,7 +1642,7 @@ typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap; template <class D, class O> static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map, - ClangASTImporter *importer, ASTContext &dest_ctx) { + ClangASTSource &source) { // When importing fields into a new record, clang has a hard requirement that // fields be imported in field offset order. Since they are stored in a // DenseMap @@ -1516,7 +1663,7 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, for (const auto &item : sorted_items) { DeclFromUser<D> user_decl(const_cast<D *>(item.first)); - DeclFromParser<D> parser_decl(user_decl.Import(importer, dest_ctx)); + DeclFromParser<D> parser_decl(user_decl.Import(source)); if (parser_decl.IsInvalid()) return false; destination_map.insert( @@ -1593,7 +1740,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, DeclFromParser<const RecordDecl> parser_record(record); DeclFromUser<const RecordDecl> origin_record( - parser_record.GetOrigin(m_ast_importer_sp.get())); + parser_record.GetOrigin(*this)); if (origin_record.IsInvalid()) return false; @@ -1629,7 +1776,7 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, field_idx++; } - ASTContext &parser_ast_context(record->getASTContext()); + lldbassert(&record->getASTContext() == m_ast_context); DeclFromUser<const CXXRecordDecl> origin_cxx_record( DynCast<const CXXRecordDecl>(origin_record)); @@ -1642,12 +1789,10 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, return false; } - if (!ImportOffsetMap(field_offsets, origin_field_offsets, - m_ast_importer_sp.get(), parser_ast_context) || - !ImportOffsetMap(base_offsets, origin_base_offsets, - m_ast_importer_sp.get(), parser_ast_context) || + if (!ImportOffsetMap(field_offsets, origin_field_offsets, *this) || + !ImportOffsetMap(base_offsets, origin_base_offsets, *this) || !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, - m_ast_importer_sp.get(), parser_ast_context)) + *this)) return false; size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); @@ -1811,8 +1956,7 @@ NamespaceDecl *ClangASTSource::AddNamespace( if (!src_namespace_decl) return nullptr; - Decl *copied_decl = - m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + Decl *copied_decl = CopyDecl(src_namespace_decl); if (!copied_decl) return nullptr; @@ -1830,6 +1974,54 @@ NamespaceDecl *ClangASTSource::AddNamespace( return dyn_cast<NamespaceDecl>(copied_decl); } +clang::QualType ClangASTSource::CopyTypeWithMerger( + clang::ASTContext &from_context, + clang::ExternalASTMerger &merger, + clang::QualType type) { + if (!merger.HasImporterForOrigin(from_context)) { + lldbassert(0 && "Couldn't find the importer for a source context!"); + return QualType(); + } + + return merger.ImporterForOrigin(from_context).Import(type); +} + +clang::Decl *ClangASTSource::CopyDecl(Decl *src_decl) { + clang::ASTContext &from_context = src_decl->getASTContext(); + if (m_ast_importer_sp) { + return m_ast_importer_sp->CopyDecl(m_ast_context, &from_context, src_decl); + } else if (m_merger_up) { + if (!m_merger_up->HasImporterForOrigin(from_context)) { + lldbassert(0 && "Couldn't find the importer for a source context!"); + return nullptr; + } + + return m_merger_up->ImporterForOrigin(from_context).Import(src_decl); + } else { + lldbassert(0 && "No mechanism for copying a decl!"); + return nullptr; + } +} + +bool ClangASTSource::ResolveDeclOrigin(const clang::Decl *decl, + clang::Decl **original_decl, + clang::ASTContext **original_ctx) { + if (m_ast_importer_sp) { + return m_ast_importer_sp->ResolveDeclOrigin(decl, original_decl, + original_ctx); + } else if (m_merger_up) { + return false; // Implement this correctly in ExternalASTMerger + } else { + // this can happen early enough that no ExternalASTSource is installed. + return false; + } +} + +clang::ExternalASTMerger &ClangASTSource::GetMergerUnchecked() { + lldbassert(m_merger_up != nullptr); + return *m_merger_up; +} + CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); @@ -1840,9 +2032,20 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { SetImportInProgress(true); - QualType copied_qual_type = - m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), - ClangUtil::GetQualType(src_type)); + QualType copied_qual_type; + + if (m_ast_importer_sp) { + copied_qual_type = + m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), + ClangUtil::GetQualType(src_type)); + } else if (m_merger_up) { + copied_qual_type = + CopyTypeWithMerger(*src_ast->getASTContext(), *m_merger_up, + ClangUtil::GetQualType(src_type)); + } else { + lldbassert(0 && "No mechanism for copying a type!"); + return CompilerType(); + } SetImportInProgress(false); diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 6362f04cf488..6f72ad92dc8c 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -16,6 +16,7 @@ #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" +#include "clang/AST/ExternalASTMerger.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/SmallSet.h" @@ -41,14 +42,10 @@ public: /// /// Initializes class variables. /// - /// @param[in] declMap - /// A reference to the LLDB object that handles entity lookup. + /// @param[in] target + /// A reference to the target containing debug information to use. //------------------------------------------------------------------ - ClangASTSource(const lldb::TargetSP &target) - : m_import_in_progress(false), m_lookups_enabled(false), m_target(target), - m_ast_context(NULL), m_active_lexical_decls(), m_active_lookups() { - m_ast_importer_sp = m_target->GetClangASTImporter(); - } + ClangASTSource(const lldb::TargetSP &target); //------------------------------------------------------------------ /// Destructor @@ -70,10 +67,9 @@ public: } void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } - void InstallASTContext(clang::ASTContext *ast_context) { - m_ast_context = ast_context; - m_ast_importer_sp->InstallMapCompleter(ast_context, *this); - } + void InstallASTContext(clang::ASTContext &ast_context, + clang::FileManager &file_manager, + bool is_shared_context = false); // // APIs for ExternalASTSource @@ -313,7 +309,7 @@ protected: /// the complete interface otherwise. //------------------------------------------------------------------ clang::ObjCInterfaceDecl * - GetCompleteObjCInterface(clang::ObjCInterfaceDecl *interface_decl); + GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl); //------------------------------------------------------------------ /// Find all entities matching a given name in a given module, @@ -376,6 +372,89 @@ protected: //------------------------------------------------------------------ CompilerType GuardedCopyType(const CompilerType &src_type); +public: + //------------------------------------------------------------------ + /// Returns true if a name should be ignored by name lookup. + /// + /// @param[in] name + /// The name to be considered. + /// + /// @param[in] ignore_all_dollar_nmmes + /// True if $-names of all sorts should be ignored. + /// + /// @return + /// True if the name is one of a class of names that are ignored by + /// global lookup for performance reasons. + //------------------------------------------------------------------ + bool IgnoreName(const ConstString name, bool ignore_all_dollar_names); + +public: + //------------------------------------------------------------------ + /// Copies a single Decl into the parser's AST context. + /// + /// @param[in] src_decl + /// The Decl to copy. + /// + /// @return + /// A copy of the Decl in m_ast_context, or NULL if the copy failed. + //------------------------------------------------------------------ + clang::Decl *CopyDecl(clang::Decl *src_decl); + + //------------------------------------------------------------------ + /// Copies a single Type to the target of the given ExternalASTMerger. + /// + /// @param[in] src_context + /// The ASTContext containing the type. + /// + /// @param[in] merger + /// The merger to use. This isn't just *m_merger_up because it might be + /// the persistent AST context's merger. + /// + /// @param[in] type + /// The type to copy. + /// + /// @return + /// A copy of the Type in the merger's target context. + //------------------------------------------------------------------ + clang::QualType CopyTypeWithMerger(clang::ASTContext &src_context, + clang::ExternalASTMerger &merger, + clang::QualType type); + + //------------------------------------------------------------------ + /// Determined the origin of a single Decl, if it can be found. + /// + /// @param[in] decl + /// The Decl whose origin is to be found. + /// + /// @param[out] original_decl + /// A pointer whose target is filled in with the original Decl. + /// + /// @param[in] original_ctx + /// A pointer whose target is filled in with the original's ASTContext. + /// + /// @return + /// True if lookup succeeded; false otherwise. + //------------------------------------------------------------------ + bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl, + clang::ASTContext **original_ctx); + + //------------------------------------------------------------------ + /// Returns m_merger_up. Only call this if the target is configured to use + /// modern lookup, + //------------------------------------------------------------------ + clang::ExternalASTMerger &GetMergerUnchecked(); + + //------------------------------------------------------------------ + /// Returns true if there is a merger. This only occurs if the target is + /// using modern lookup. + //------------------------------------------------------------------ + bool HasMerger() { return (bool)m_merger_up; } + +protected: + bool FindObjCMethodDeclsWithOrigin( + unsigned int current_id, NameSearchContext &context, + clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info); + friend struct NameSearchContext; bool m_import_in_progress; @@ -385,7 +464,11 @@ protected: m_target; ///< The target to use in finding variables and types. clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + clang::FileManager + *m_file_manager; ///< The file manager paired with the AST context. lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::unique_ptr<clang::ExternalASTMerger> m_merger_up; + ///< The ExternalASTMerger for this parse. std::set<const clang::Decl *> m_active_lexical_decls; std::set<const char *> m_active_lookups; }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 8fde41052192..07ff2e97aac7 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -48,8 +48,10 @@ #include "lldb/lldb-private.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTImporter.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" @@ -178,6 +180,134 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() { return ret; } +namespace { +/// This class walks an AST and ensures that all DeclContexts defined inside the +/// current source file are properly complete. +/// +/// This is used to ensure that persistent types defined in the current source +/// file migrate completely to the persistent AST context before they are +/// reused. If that didn't happen, it would be impoossible to complete them +/// because their origin would be gone. +/// +/// The stragtegy used by this class is to check the SourceLocation (to be +/// specific, the FileID) and see if it's the FileID for the current expression. +/// Alternate strategies could include checking whether an ExternalASTMerger, +/// set up to not have the current context as a source, can find an original for +/// the type. +class Completer : public clang::RecursiveASTVisitor<Completer> { +private: + clang::ASTImporter &m_exporter; /// Used to import Decl contents + clang::FileID m_file; /// The file that's going away + llvm::DenseSet<clang::Decl *> m_completed; /// Visited Decls, to avoid cycles + + bool ImportAndCheckCompletable(clang::Decl *decl) { + (void)m_exporter.Import(decl); + if (m_completed.count(decl)) + return false; + if (!llvm::isa<DeclContext>(decl)) + return false; + const clang::SourceLocation loc = decl->getLocation(); + if (!loc.isValid()) + return false; + const clang::FileID file = + m_exporter.getFromContext().getSourceManager().getFileID(loc); + if (file != m_file) + return false; + // We are assuming the Decl was parsed in this very expression, so it should + // not have external storage. + lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage()); + return true; + } + + void Complete(clang::Decl *decl) { + m_completed.insert(decl); + auto *decl_context = llvm::cast<DeclContext>(decl); + (void)m_exporter.Import(decl); + m_exporter.CompleteDecl(decl); + for (Decl *child : decl_context->decls()) + if (ImportAndCheckCompletable(child)) + Complete(child); + } + + void MaybeComplete(clang::Decl *decl) { + if (ImportAndCheckCompletable(decl)) + Complete(decl); + } + +public: + Completer(clang::ASTImporter &exporter, clang::FileID file) + : m_exporter(exporter), m_file(file) {} + + // Implements the RecursiveASTVisitor's core API. It is called on each Decl + // that the RecursiveASTVisitor encounters, and returns true if the traversal + // should continue. + bool VisitDecl(clang::Decl *decl) { + MaybeComplete(decl); + return true; + } +}; +} + +static void CompleteAllDeclContexts(clang::ASTImporter &exporter, + clang::FileID file, + clang::QualType root) { + clang::QualType canonical_type = root.getCanonicalType(); + if (clang::TagDecl *tag_decl = canonical_type->getAsTagDecl()) { + Completer(exporter, file).TraverseDecl(tag_decl); + } else if (auto interface_type = llvm::dyn_cast<ObjCInterfaceType>( + canonical_type.getTypePtr())) { + Completer(exporter, file).TraverseDecl(interface_type->getDecl()); + } else { + Completer(exporter, file).TraverseType(canonical_type); + } +} + +static clang::QualType ExportAllDeclaredTypes( + clang::ExternalASTMerger &merger, + clang::ASTContext &source, clang::FileManager &source_file_manager, + const clang::ExternalASTMerger::OriginMap &source_origin_map, + clang::FileID file, clang::QualType root) { + clang::ExternalASTMerger::ImporterSource importer_source = + { source, source_file_manager, source_origin_map }; + merger.AddSources(importer_source); + clang::ASTImporter &exporter = merger.ImporterForOrigin(source); + CompleteAllDeclContexts(exporter, file, root); + clang::QualType ret = exporter.Import(root); + merger.RemoveSources(importer_source); + return ret; +} + +TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target, + ClangASTContext &source, + TypeFromParser parser_type) { + assert (&target == m_target->GetScratchClangASTContext()); + assert ((TypeSystem*)&source == parser_type.GetTypeSystem()); + assert (source.getASTContext() == m_ast_context); + + if (m_ast_importer_sp) { + return TypeFromUser(m_ast_importer_sp->DeportType( + target.getASTContext(), source.getASTContext(), + parser_type.GetOpaqueQualType()), + &target); + } else if (m_merger_up) { + clang::FileID source_file = + source.getASTContext()->getSourceManager().getFileID( + source.getASTContext()->getTranslationUnitDecl()->getLocation()); + auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>( + m_target->GetScratchClangASTContext()); + clang::QualType exported_type = ExportAllDeclaredTypes( + scratch_ast_context->GetMergerUnchecked(), + *source.getASTContext(), *source.getFileManager(), + m_merger_up->GetOrigins(), + source_file, + clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType())); + return TypeFromUser(exported_type.getAsOpaquePtr(), &target); + } else { + lldbassert(0 && "No mechanism for deporting a type!"); + return TypeFromUser(); + } +} + bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, const ConstString &name, TypeFromParser parser_type, @@ -198,12 +328,8 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, if (target == nullptr) return false; - ClangASTContext *context(target->GetScratchClangASTContext()); - - TypeFromUser user_type(m_ast_importer_sp->DeportType( - context->getASTContext(), ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); + TypeFromUser user_type = + DeportType(*target->GetScratchClangASTContext(), *ast, parser_type); uint32_t offset = m_parser_vars->m_materializer->AddResultVariable( user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err); @@ -240,10 +366,7 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl, ClangASTContext *context(target->GetScratchClangASTContext()); - TypeFromUser user_type(m_ast_importer_sp->DeportType( - context->getASTContext(), ast->getASTContext(), - parser_type.GetOpaqueQualType()), - context); + TypeFromUser user_type = DeportType(*context, *ast, parser_type); if (!user_type.GetOpaqueQualType()) { if (log) @@ -688,16 +811,18 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } ClangASTImporter::NamespaceMapSP namespace_map = - m_ast_importer_sp->GetNamespaceMap(namespace_context); + m_ast_importer_sp + ? m_ast_importer_sp->GetNamespaceMap(namespace_context) + : ClangASTImporter::NamespaceMapSP(); + + if (!namespace_map) + return; if (log && log->GetVerbose()) log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", current_id, static_cast<void *>(namespace_map.get()), (int)namespace_map->size()); - - if (!namespace_map) - return; - + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); i != e; ++i) { @@ -739,16 +864,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( SymbolContextList sc_list; const ConstString name(context.m_decl_name.getAsString().c_str()); - - const char *name_unique_cstr = name.GetCString(); - - if (name_unique_cstr == NULL) - return; - - static ConstString id_name("id"); - static ConstString Class_name("Class"); - - if (name == id_name || name == Class_name) + if (IgnoreName(name, false)) return; // Only look for functions by name out in our symbols if the function @@ -784,8 +900,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (!persistent_decl) break; - Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, scratch_ast_context, persistent_decl); + Decl *parser_persistent_decl = CopyDecl(persistent_decl); if (!parser_persistent_decl) break; @@ -809,7 +924,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } while (0); } - if (name_unique_cstr[0] == '$' && !namespace_decl) { + if (name.GetCString()[0] == '$' && !namespace_decl) { static ConstString g_lldb_class_name("$__lldb_class"); if (name == g_lldb_class_name) { @@ -1041,7 +1156,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (ast) { clang::NamespaceDecl *namespace_decl = ClangASTContext::GetUniqueNamespaceDeclaration( - m_ast_context, name_unique_cstr, nullptr); + m_ast_context, name.GetCString(), nullptr); if (namespace_decl) { context.AddNamedDecl(namespace_decl); clang::DeclContext *clang_decl_ctx = @@ -1056,7 +1171,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } // any other $__lldb names should be weeded out now - if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + if (name.GetStringRef().startswith("$__lldb")) return; ExpressionVariableSP pvar_sp( @@ -1329,8 +1444,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( for (clang::NamedDecl *decl : decls_from_modules) { if (llvm::isa<clang::FunctionDecl>(decl)) { clang::NamedDecl *copied_decl = - llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl( - m_ast_context, &decl->getASTContext(), decl)); + llvm::cast_or_null<FunctionDecl>(CopyDecl(decl)); if (copied_decl) { context.AddNamedDecl(copied_decl); context.m_found.function_with_type_info = true; @@ -1372,9 +1486,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr; @@ -1401,9 +1513,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( current_id, name.GetCString()); } - clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl( - m_ast_context, &decl_from_modules->getASTContext(), - decl_from_modules); + clang::Decl *copied_decl = CopyDecl(decl_from_modules); clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr; @@ -1430,17 +1540,17 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( // a generic // data symbol, and -- if it is found -- treat it as a variable. Status error; - + const Symbol *data_symbol = m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error); - + if (!error.Success()) { const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Level::Error, "%0"); m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString(); } - + if (data_symbol) { std::string warning("got name from symbols: "); warning.append(name.AsCString()); @@ -1455,49 +1565,6 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } } -// static opaque_compiler_type_t -// MaybePromoteToBlockPointerType -//( -// ASTContext *ast_context, -// opaque_compiler_type_t candidate_type -//) -//{ -// if (!candidate_type) -// return candidate_type; -// -// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); -// -// const PointerType *candidate_pointer_type = -// dyn_cast<PointerType>(candidate_qual_type); -// -// if (!candidate_pointer_type) -// return candidate_type; -// -// QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); -// -// const RecordType *pointee_record_type = -// dyn_cast<RecordType>(pointee_qual_type); -// -// if (!pointee_record_type) -// return candidate_type; -// -// RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); -// -// if (!pointee_record_decl->isRecord()) -// return candidate_type; -// -// if -// (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) -// return candidate_type; -// -// QualType generic_function_type = -// ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); -// QualType block_pointer_type = -// ast_context->getBlockPointerType(generic_function_type); -// -// return block_pointer_type.getAsOpaquePtr(); -//} - bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, lldb_private::Value &var_location, TypeFromUser *user_type, @@ -1537,7 +1604,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, "There is no AST context for the current execution context"); return false; } - // var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); DWARFExpression &var_location_expr = var->LocationExpression(); @@ -1762,7 +1828,9 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + ClangASTContextForExpressions *scratch_ast_context = + static_cast<ClangASTContextForExpressions*>( + target->GetScratchClangASTContext()); for (size_t index = 0, num_entities = m_found_entities.GetSize(); index < num_entities; ++index) { @@ -1793,9 +1861,20 @@ bool ClangExpressionDeclMap::ResolveUnknownTypes() { var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); - lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType( - scratch_ast_context->getASTContext(), &var_decl->getASTContext(), - var_type.getAsOpaquePtr()); + lldb::opaque_compiler_type_t copied_type = 0; + if (m_ast_importer_sp) { + copied_type = m_ast_importer_sp->CopyType( + scratch_ast_context->getASTContext(), &var_decl->getASTContext(), + var_type.getAsOpaquePtr()); + } else if (HasMerger()) { + copied_type = CopyTypeWithMerger( + var_decl->getASTContext(), + scratch_ast_context->GetMergerUnchecked(), + var_type).getAsOpaquePtr(); + } else { + lldbassert(0 && "No mechanism to copy a resolved unknown type!"); + return false; + } if (!copied_type) { if (log) @@ -1892,8 +1971,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, if (!extern_c) { TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); - if (ClangASTContext *src_ast = - llvm::dyn_cast<ClangASTContext>(type_system)) { + if (llvm::isa<ClangASTContext>(type_system)) { clang::DeclContext *src_decl_context = (clang::DeclContext *)function->GetDeclContext() .GetOpaqueDeclContext(); @@ -1905,9 +1983,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, src_function_decl->getTemplateSpecializationInfo()->getTemplate(); clang::FunctionTemplateDecl *copied_function_template = llvm::dyn_cast_or_null<clang::FunctionTemplateDecl>( - m_ast_importer_sp->CopyDecl(m_ast_context, - src_ast->getASTContext(), - function_template)); + CopyDecl(function_template)); if (copied_function_template) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_template); @@ -1928,9 +2004,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, } else if (src_function_decl) { if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>( - m_ast_importer_sp->CopyDecl(m_ast_context, - src_ast->getASTContext(), - src_function_decl))) { + CopyDecl(src_function_decl))) { if (log) { ASTDumper ast_dumper((clang::Decl *)copied_function_decl); diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index e8a9ba6862db..d163ad4f7e29 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -613,6 +613,23 @@ private: void AddThisType(NameSearchContext &context, TypeFromUser &type, unsigned int current_id); + //------------------------------------------------------------------ + /// Move a type out of the current ASTContext into another, but make sure to + /// export all components of the type also. + /// + /// @param[in] target + /// The ClangASTContext to move to. + /// @param[in] source + /// The ClangASTContext to move from. This is assumed to be going away. + /// @param[in] parser_type + /// The type as it appears in the source context. + /// + /// @return + /// Returns the moved type, or an empty type if there was a problem. + //------------------------------------------------------------------ + TypeFromUser DeportType(ClangASTContext &target, ClangASTContext &source, + TypeFromParser parser_type); + ClangASTContext *GetClangASTContext(); }; diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 4e20be79f68b..d9e53074b3fb 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -66,7 +66,6 @@ #include "ClangPersistentVariables.h" #include "IRForTarget.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" @@ -351,7 +350,6 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, LLDB_LOGV(log, "LinkerVersion: '{0}'", opts.LinkerVersion); StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); StringList::LogDump(log, opts.Features, "Features"); - StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); } // 4. Create and install the target on the compiler. @@ -391,6 +389,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, // FIXME: the following language option is a temporary workaround, // to "ask for ObjC, get ObjC++" (see comment above). m_compiler->getLangOpts().CPlusPlus = true; + + // Clang now sets as default C++14 as the default standard (with + // GNU extensions), so we do the same here to avoid mismatches that + // cause compiler error when evaluating expressions (e.g. nullptr + // not found as it's a C++11 feature). Currently lldb evaluates + // C++14 as C++11 (see two lines below) so we decide to be consistent + // with that, but this could be re-evaluated in the future. + m_compiler->getLangOpts().CPlusPlus11 = true; break; case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeC_plus_plus_11: @@ -526,7 +532,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, if (decl_map) { llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source( decl_map->CreateProxy()); - decl_map->InstallASTContext(ast_context.get()); + decl_map->InstallASTContext(*ast_context, m_compiler->getFileManager()); ast_context->setExternalSource(ast_source); } diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 3e6a109a4af3..41f290f2e127 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -10,10 +10,10 @@ #ifndef liblldb_ClangExpressionParser_h_ #define liblldb_ClangExpressionParser_h_ -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionParser.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Status.h" #include "lldb/lldb-public.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 56d1d8412f78..0596d8fde7b9 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -17,7 +17,6 @@ #include "ClangExpressionHelper.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectList.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index bce0eaf6d57e..b42ceb9afee8 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -85,6 +85,7 @@ public: void ForEachMacro(const ModuleVector &modules, std::function<bool(const std::string &)> handler) override; + clang::ExternalASTMerger::ImporterSource GetImporterSource() override; private: void ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -109,6 +110,7 @@ private: typedef std::set<ModuleID> ImportedModuleSet; ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; + const clang::ExternalASTMerger::OriginMap m_origin_map; }; } // anonymous namespace @@ -548,6 +550,12 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, is_inclusion_directive); } +clang::ExternalASTMerger::ImporterSource +ClangModulesDeclVendorImpl::GetImporterSource() { + return {m_compiler_instance->getASTContext(), + m_compiler_instance->getFileManager(), m_origin_map}; +} + static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; lldb_private::ClangModulesDeclVendor * diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h index fbabcd736865..23769ccfb0c0 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -10,7 +10,6 @@ #ifndef liblldb_ClangModulesDeclVendor_h #define liblldb_ClangModulesDeclVendor_h -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Symbol/DeclVendor.h" #include "lldb/Target/Platform.h" diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 2a6261a6df4d..18fe8b49227b 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -347,7 +347,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, // ApplyObjcCastHack(m_expr_text); - // ApplyUnicharHack(m_expr_text); std::string prefix = m_expr_prefix; diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 065e5db4c9f8..0f2aeef27e57 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -138,15 +138,6 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, } } -#if 0 - // jingham: look here - StreamFile logfile ("/tmp/exprs.txt", "a"); - logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", - m_jit_start_addr, - m_function_name.c_str(), - m_function_text.c_str()); -#endif - DeclMap()->DidParse(); ResetDeclMap(); diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index d0ef688f0773..262a7914d249 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -12,12 +12,12 @@ #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/PosixApi.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 5e90965c1881..d1032f56f31c 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -203,7 +203,8 @@ size_t EmulationStateARM::WritePseudoMemory( uint32_t value1; uint32_t value2; memcpy (&value1, dst, sizeof (uint32_t)); - memcpy (&value2, (uint8_t *) dst + sizeof (uint32_t), sizeof (uint32_t)); + memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t), + sizeof(uint32_t)); if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { value1 = llvm::ByteSwap_32(value1); value2 = llvm::ByteSwap_32(value2); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 54dd237eb4b7..d882108c25f4 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -12,10 +12,10 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" @@ -167,10 +167,7 @@ EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { - std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap( - new EmulateInstructionARM64(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionARM64(arch); } } diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 4d1d89abb1d0..db3d8fc1b8ca 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -12,12 +12,12 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" @@ -212,10 +212,7 @@ EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch, inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel) { - std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap( - new EmulateInstructionMIPS(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionMIPS(arch); } } diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 1e6d98756958..d298589afdd9 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -12,12 +12,12 @@ #include <stdlib.h> #include "lldb/Core/Address.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Host/PosixApi.h" #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" @@ -199,10 +199,7 @@ EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch, inst_type)) { if (arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) { - std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap( - new EmulateInstructionMIPS64(arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); + return new EmulateInstructionMIPS64(arch); } } @@ -801,7 +798,9 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { // Branch instructions //---------------------------------------------------------------------- {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, + {"BEQ64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, + {"BNE64", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset"}, {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, @@ -814,6 +813,7 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"}, {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"}, {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, + {"BGEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, "BLEZALC rs,offset"}, {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, @@ -828,34 +828,61 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { "BNEZALC rs,offset"}, {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset"}, + {"BEQC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BEQC rs,rt,offset"}, {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset"}, + {"BNEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BNEC rs,rt,offset"}, {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset"}, + {"BLTC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTC rs,rt,offset"}, {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset"}, + {"BGEC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEC rs,rt,offset"}, {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset"}, + {"BLTUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTUC rs,rt,offset"}, {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset"}, + {"BGEUC64", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEUC rs,rt,offset"}, {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset"}, + {"BLTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLTZC rt,offset"}, {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset"}, + {"BLEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLEZC rt,offset"}, {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset"}, + {"BGEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGEZC rt,offset"}, {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset"}, + {"BGTZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGTZC rt,offset"}, {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset"}, + {"BEQZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BEQZC rt,offset"}, {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset"}, + {"BNEZC64", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BNEZC rt,offset"}, {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"}, {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, + {"BGTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"}, {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, + {"BLEZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"}, {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, + {"BLTZ64", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset"}, {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, @@ -872,8 +899,11 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"}, {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, + {"JIALC64", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, + {"JIC64", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, + {"JR64", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"}, {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"}, {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"}, @@ -1338,12 +1368,14 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")) { + if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL") + || !strcasecmp(op_name, "BEQ64") ) { if (rs_val == rt_val) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")) { + } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL") + || !strcasecmp(op_name, "BNE64")) { if (rs_val != rt_val) target = pc + offset; else @@ -1563,22 +1595,26 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")) { + if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ") + || !strcasecmp(op_name, "BLTZ64")) { if (rs_val < 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")) { + } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ") + || !strcasecmp(op_name, "BGEZ64")) { if (rs_val >= 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")) { + } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ") + || !strcasecmp(op_name, "BGTZ64")) { if (rs_val > 0) target = pc + offset; else target = pc + 8; - } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")) { + } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ") + || !strcasecmp(op_name, "BLEZ64")) { if (rs_val <= 0) target = pc + offset; else @@ -1657,32 +1693,32 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BEQC")) { + if (!strcasecmp(op_name, "BEQC") || !strcasecmp(op_name, "BEQC64")) { if (rs_val == rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BNEC")) { + } else if (!strcasecmp(op_name, "BNEC") || !strcasecmp(op_name, "BNEC64")) { if (rs_val != rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLTC")) { + } else if (!strcasecmp(op_name, "BLTC") || !strcasecmp(op_name, "BLTC64")) { if (rs_val < rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEC")) { + } else if (!strcasecmp(op_name, "BGEC64") || !strcasecmp(op_name, "BGEC")) { if (rs_val >= rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLTUC")) { + } else if (!strcasecmp(op_name, "BLTUC") || !strcasecmp(op_name, "BLTUC64")) { if (rs_val < rt_val) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEUC")) { + } else if (!strcasecmp(op_name, "BGEUC") || !strcasecmp(op_name, "BGEUC64")) { if ((uint32_t)rs_val >= (uint32_t)rt_val) target = pc + offset; else @@ -1734,32 +1770,32 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) { if (!success) return false; - if (!strcasecmp(op_name, "BLTZC")) { + if (!strcasecmp(op_name, "BLTZC") || !strcasecmp(op_name, "BLTZC64")) { if (rs_val < 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BLEZC")) { + } else if (!strcasecmp(op_name, "BLEZC") || !strcasecmp(op_name, "BLEZC64")) { if (rs_val <= 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGEZC")) { + } else if (!strcasecmp(op_name, "BGEZC") || !strcasecmp(op_name, "BGEZC64")) { if (rs_val >= 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BGTZC")) { + } else if (!strcasecmp(op_name, "BGTZC") || !strcasecmp(op_name, "BGTZC64")) { if (rs_val > 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BEQZC")) { + } else if (!strcasecmp(op_name, "BEQZC") || !strcasecmp(op_name, "BEQZC64")) { if (rs_val == 0) target = pc + offset; else target = pc + 4; - } else if (!strcasecmp(op_name, "BNEZC")) { + } else if (!strcasecmp(op_name, "BNEZC") || !strcasecmp(op_name, "BNEZC64")) { if (rs_val != 0) target = pc + offset; else diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 8f769c499987..180440a244a4 100644 --- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -5,9 +5,12 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN CxxStringTypes.cpp LibCxx.cpp LibCxxAtomic.cpp + LibCxxBitset.cpp LibCxxInitializerList.cpp LibCxxList.cpp LibCxxMap.cpp + LibCxxQueue.cpp + LibCxxTuple.cpp LibCxxUnorderedMap.cpp LibCxxVector.cpp LibStdcpp.cpp diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 1ae9418e4d9c..51ed88065c84 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -422,12 +422,24 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator, + "libc++ std::bitset synthetic children", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags, + true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags, true); AddCXXSynthetic( cpp_category_sp, + lldb_private::formatters::LibcxxStdForwardListSyntheticFrontEndCreator, + "libc++ std::forward_list synthetic children", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic( + cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true); @@ -467,6 +479,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxQueueFrontEndCreator, + "libc++ std::queue synthetic children", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, LibcxxTupleFrontEndCreator, + "libc++ std::tuple synthetic children", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags, + true); AddCXXSynthetic( cpp_category_sp, lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator, @@ -497,12 +517,22 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags.SetSkipPointers(false); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::bitset summary provider", + ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", + ConstString("^std::__(ndk)?1::forward_list<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::list summary provider", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_summary_flags, true); AddCXXSummary(cpp_category_sp, @@ -517,6 +547,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { stl_summary_flags, true); AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, + "libc++ std::queue summary provider", + ConstString("^std::__(ndk)?1::queue<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, + lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"), stl_summary_flags, true); @@ -535,6 +570,10 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { "libc++ std::unordered containers summary provider", ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, LibcxxContainerSummaryProvider, + "libc++ std::tuple summary provider", + ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_summary_flags, + true); AddCXXSummary( cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider, "libc++ std::atomic summary provider", diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp index 88bdd68ff301..aebea6ae3569 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp @@ -628,7 +628,7 @@ static const clang::LangOptions &GetLangOptions() { g_options.CPlusPlus = true; g_options.CPlusPlus11 = true; g_options.CPlusPlus14 = true; - g_options.CPlusPlus1z = true; + g_options.CPlusPlus17 = true; }); return g_options; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 11245e1310b7..f6d1f18cb596 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -153,12 +153,11 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() { .get(); if (m_pair_ptr) { auto __i_(valobj_sp->GetChildMemberWithName(g___i_, true)); - lldb::TemplateArgumentKind kind; if (!__i_) { m_pair_ptr = nullptr; return false; } - CompilerType pair_type(__i_->GetCompilerType().GetTemplateArgument(0, kind)); + CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0)); std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr; pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr); if (!pair_type) { diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h index 7610212b4245..3f6e0d6e14d7 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -93,6 +93,10 @@ private: }; SyntheticChildrenFrontEnd * +LibcxxBitsetSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -105,6 +109,10 @@ LibcxxStdListSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); SyntheticChildrenFrontEnd * +LibcxxStdForwardListSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd * LibcxxStdMapSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); @@ -119,6 +127,12 @@ LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *, SyntheticChildrenFrontEnd *LibcxxFunctionFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + +SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP); + } // namespace formatters } // namespace lldb_private diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp new file mode 100644 index 000000000000..0cdb0b26cf3b --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -0,0 +1,107 @@ +//===-- LibCxxBitset.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class BitsetFrontEnd : public SyntheticChildrenFrontEnd { +public: + BitsetFrontEnd(ValueObject &valobj); + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_first; + CompilerType m_bool_type; + ByteOrder m_byte_order = eByteOrderInvalid; + uint8_t m_byte_size = 0; +}; +} // namespace + +BitsetFrontEnd::BitsetFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) { + m_bool_type = valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeBool); + if (auto target_sp = m_backend.GetTargetSP()) { + m_byte_order = target_sp->GetArchitecture().GetByteOrder(); + m_byte_size = target_sp->GetArchitecture().GetAddressByteSize(); + Update(); + } +} + +bool BitsetFrontEnd::Update() { + m_elements.clear(); + m_first.reset(); + + TargetSP target_sp = m_backend.GetTargetSP(); + if (!target_sp) + return false; + size_t capping_size = target_sp->GetMaximumNumberOfChildrenToDisplay(); + + size_t size = 0; + if (auto arg = m_backend.GetCompilerType().GetIntegralTemplateArgument(0)) + size = arg->value.getLimitedValue(capping_size); + + m_elements.assign(size, ValueObjectSP()); + + m_first = m_backend.GetChildMemberWithName(ConstString("__first_"), true); + return false; +} + +ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size() || !m_first) + return ValueObjectSP(); + + if (m_elements[idx]) + return m_elements[idx]; + + ExecutionContext ctx = m_backend.GetExecutionContextRef().Lock(false); + CompilerType type; + ValueObjectSP chunk; + // For small bitsets __first_ is not an array, but a plain size_t. + if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) + chunk = m_first->GetChildAtIndex( + idx / type.GetBitSize(ctx.GetBestExecutionContextScope()), true); + else { + type = m_first->GetCompilerType(); + chunk = m_first; + } + if (!type || !chunk) + return ValueObjectSP(); + + size_t chunk_idx = idx % type.GetBitSize(ctx.GetBestExecutionContextScope()); + uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx)); + DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size); + + m_elements[idx] = CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), + data, ctx, m_bool_type); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd *formatters::LibcxxBitsetSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new BitsetFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp index 4e839532afb7..5823f6f3e038 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -94,9 +94,8 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd:: m_start = nullptr; m_num_elements = 0; - lldb::TemplateArgumentKind kind; - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); - if (kind != lldb::eTemplateArgumentKindType || !m_element_type.IsValid()) + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); + if (!m_element_type.IsValid()) return false; m_element_size = m_element_type.GetByteSize(nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 56d8edaba72a..6407ae129ad7 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -114,58 +114,90 @@ private: ListEntry m_entry; }; -} // end anonymous namespace - -namespace lldb_private { -namespace formatters { -class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class AbstractListFrontEnd : public SyntheticChildrenFrontEnd { public: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + size_t GetIndexOfChildWithName(const ConstString &name) override { + return ExtractIndexFromString(name.GetCString()); + } + bool MightHaveChildren() override { return true; } + bool Update() override; - ~LibcxxStdListSyntheticFrontEnd() override = default; +protected: + AbstractListFrontEnd(ValueObject &valobj) + : SyntheticChildrenFrontEnd(valobj) {} - size_t CalculateNumChildren() override; + size_t m_count; + ValueObject *m_head; - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + static constexpr bool g_use_loop_detect = true; + size_t m_loop_detected; // The number of elements that have had loop detection + // run over them. + ListEntry m_slow_runner; // Used for loop detection + ListEntry m_fast_runner; // Used for loop detection + + size_t m_list_capping_size; + CompilerType m_element_type; + std::map<size_t, ListIterator> m_iterators; + + bool HasLoop(size_t count); + ValueObjectSP GetItem(size_t idx); +}; +class ForwardListFrontEnd : public AbstractListFrontEnd { +public: + ForwardListFrontEnd(ValueObject &valobj); + + size_t CalculateNumChildren() override; + ValueObjectSP GetChildAtIndex(size_t idx) override; bool Update() override; +}; - bool MightHaveChildren() override; +class ListFrontEnd : public AbstractListFrontEnd { +public: + ListFrontEnd(lldb::ValueObjectSP valobj_sp); - size_t GetIndexOfChildWithName(const ConstString &name) override; + ~ListFrontEnd() override = default; -private: - bool HasLoop(size_t count); + size_t CalculateNumChildren() override; - size_t m_list_capping_size; - static const bool g_use_loop_detect = true; + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - size_t m_loop_detected; // The number of elements that have had loop detection - // run over them. - ListEntry m_slow_runner; // Used for loop detection - ListEntry m_fast_runner; // Used for loop detection + bool Update() override; +private: lldb::addr_t m_node_address; - ValueObject *m_head; ValueObject *m_tail; - CompilerType m_element_type; - size_t m_count; - std::map<size_t, ListIterator> m_iterators; }; -} // namespace formatters -} // namespace lldb_private - -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - LibcxxStdListSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_list_capping_size(0), - m_loop_detected(0), m_node_address(), m_head(nullptr), m_tail(nullptr), - m_element_type(), m_count(UINT32_MAX), m_iterators() { - if (valobj_sp) - Update(); + +} // end anonymous namespace + +bool AbstractListFrontEnd::Update() { + m_loop_detected = 0; + m_count = UINT32_MAX; + m_head = nullptr; + m_list_capping_size = 0; + m_slow_runner.SetEntry(nullptr); + m_fast_runner.SetEntry(nullptr); + m_iterators.clear(); + + if (m_backend.GetTargetSP()) + m_list_capping_size = + m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + if (m_list_capping_size == 0) + m_list_capping_size = 255; + + CompilerType list_type = m_backend.GetCompilerType(); + if (list_type.IsReferenceType()) + list_type = list_type.GetNonReferenceType(); + + if (list_type.GetNumTemplateArguments() == 0) + return false; + m_element_type = list_type.GetTypeTemplateArgument(0); + + return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( - size_t count) { +bool AbstractListFrontEnd::HasLoop(size_t count) { if (!g_use_loop_detect) return false; // don't bother checking for a loop if we won't actually need to jump nodes @@ -201,8 +233,105 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop( return m_slow_runner == m_fast_runner; } -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - CalculateNumChildren() { +ValueObjectSP AbstractListFrontEnd::GetItem(size_t idx) { + size_t advance = idx; + ListIterator current(m_head); + if (idx > 0) { + auto cached_iterator = m_iterators.find(idx - 1); + if (cached_iterator != m_iterators.end()) { + current = cached_iterator->second; + advance = 1; + } + } + ValueObjectSP value_sp = current.advance(advance); + m_iterators[idx] = current; + return value_sp; +} + +ForwardListFrontEnd::ForwardListFrontEnd(ValueObject &valobj) + : AbstractListFrontEnd(valobj) { + Update(); +} + +size_t ForwardListFrontEnd::CalculateNumChildren() { + if (m_count != UINT32_MAX) + return m_count; + + ListEntry current(m_head); + m_count = 0; + while (current && m_count < m_list_capping_size) { + ++m_count; + current = current.next(); + } + return m_count; +} + +ValueObjectSP ForwardListFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= CalculateNumChildren()) + return nullptr; + + if (!m_head) + return nullptr; + + if (HasLoop(idx + 1)) + return nullptr; + + ValueObjectSP current_sp = GetItem(idx); + if (!current_sp) + return nullptr; + + current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child + if (!current_sp) + return nullptr; + + // we need to copy current_sp into a new object otherwise we will end up with + // all items named __value_ + DataExtractor data; + Status error; + current_sp->GetData(data, error); + if (error.Fail()) + return nullptr; + + return CreateValueObjectFromData(llvm::formatv("[{0}]", idx).str(), data, + m_backend.GetExecutionContextRef(), + m_element_type); +} + +static ValueObjectSP GetValueOfCompressedPair(ValueObject &pair) { + ValueObjectSP value = pair.GetChildMemberWithName(ConstString("__value_"), true); + if (! value) { + // pre-r300140 member name + value = pair.GetChildMemberWithName(ConstString("__first_"), true); + } + return value; +} + +bool ForwardListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + + Status err; + ValueObjectSP backend_addr(m_backend.AddressOf(err)); + if (err.Fail() || !backend_addr) + return false; + + ValueObjectSP impl_sp( + m_backend.GetChildMemberWithName(ConstString("__before_begin_"), true)); + if (!impl_sp) + return false; + impl_sp = GetValueOfCompressedPair(*impl_sp); + if (!impl_sp) + return false; + m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); + return false; +} + +ListFrontEnd::ListFrontEnd(lldb::ValueObjectSP valobj_sp) + : AbstractListFrontEnd(*valobj_sp), m_node_address(), m_tail(nullptr) { + if (valobj_sp) + Update(); +} + +size_t ListFrontEnd::CalculateNumChildren() { if (m_count != UINT32_MAX) return m_count; if (!m_head || !m_tail || m_node_address == 0) @@ -210,10 +339,9 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: ValueObjectSP size_alloc( m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true)); if (size_alloc) { - ValueObjectSP first( - size_alloc->GetChildMemberWithName(ConstString("__first_"), true)); - if (first) { - m_count = first->GetValueAsUnsigned(UINT32_MAX); + ValueObjectSP value = GetValueOfCompressedPair(*size_alloc); + if (value) { + m_count = value->GetValueAsUnsigned(UINT32_MAX); } } if (m_count != UINT32_MAX) { @@ -239,9 +367,7 @@ size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: } } -lldb::ValueObjectSP -lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb::ValueObjectSP ListFrontEnd::GetChildAtIndex(size_t idx) { static ConstString g_value("__value_"); static ConstString g_next("__next_"); @@ -254,23 +380,10 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( if (HasLoop(idx + 1)) return lldb::ValueObjectSP(); - size_t actual_advance = idx; - - ListIterator current(m_head); - if (idx > 0) { - auto cached_iterator = m_iterators.find(idx - 1); - if (cached_iterator != m_iterators.end()) { - current = cached_iterator->second; - actual_advance = 1; - } - } - - ValueObjectSP current_sp(current.advance(actual_advance)); + ValueObjectSP current_sp = GetItem(idx); if (!current_sp) return lldb::ValueObjectSP(); - m_iterators[idx] = current; - current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child if (!current_sp) return lldb::ValueObjectSP(); @@ -303,23 +416,13 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex( m_element_type); } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { - m_iterators.clear(); - m_head = m_tail = nullptr; +bool ListFrontEnd::Update() { + AbstractListFrontEnd::Update(); + m_tail = nullptr; m_node_address = 0; - m_count = UINT32_MAX; - m_loop_detected = 0; - m_slow_runner.SetEntry(nullptr); - m_fast_runner.SetEntry(nullptr); Status err; ValueObjectSP backend_addr(m_backend.AddressOf(err)); - m_list_capping_size = 0; - if (m_backend.GetTargetSP()) - m_list_capping_size = - m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); - if (m_list_capping_size == 0) - m_list_capping_size = 255; if (err.Fail() || !backend_addr) return false; m_node_address = backend_addr->GetValueAsUnsigned(0); @@ -329,31 +432,18 @@ bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() { m_backend.GetChildMemberWithName(ConstString("__end_"), true)); if (!impl_sp) return false; - CompilerType list_type = m_backend.GetCompilerType(); - if (list_type.IsReferenceType()) - list_type = list_type.GetNonReferenceType(); - - if (list_type.GetNumTemplateArguments() == 0) - return false; - lldb::TemplateArgumentKind kind; - m_element_type = list_type.GetTemplateArgument(0, kind); m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); return false; } -bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - MightHaveChildren() { - return true; -} - -size_t lldb_private::formatters::LibcxxStdListSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { - return ExtractIndexFromString(name.GetCString()); +SyntheticChildrenFrontEnd *formatters::LibcxxStdListSyntheticFrontEndCreator( + CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { + return (valobj_sp ? new ListFrontEnd(valobj_sp) : nullptr); } SyntheticChildrenFrontEnd * -lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator( +formatters::LibcxxStdForwardListSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { - return (valobj_sp ? new LibcxxStdListSyntheticFrontEnd(valobj_sp) : nullptr); + return valobj_sp ? new ForwardListFrontEnd(*valobj_sp) : nullptr; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index b7215dbcbb48..be96a6d95bcd 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -268,13 +268,12 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = deref->GetCompilerType(); return true; } - lldb::TemplateArgumentKind kind; deref = m_backend.GetChildAtNamePath({g_tree_, g_pair3}); if (!deref) return false; - m_element_type = - deref->GetCompilerType().GetTemplateArgument(1, kind).GetTemplateArgument( - 1, kind); + m_element_type = deref->GetCompilerType() + .GetTypeTemplateArgument(1) + .GetTypeTemplateArgument(1); if (m_element_type) { std::string name; uint64_t bit_offset_ptr; @@ -285,7 +284,7 @@ bool lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() { m_element_type = m_element_type.GetTypedefedType(); return m_element_type.IsValid(); } else { - m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); + m_element_type = m_backend.GetCompilerType().GetTypeTemplateArgument(0); return m_element_type.IsValid(); } } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp new file mode 100644 index 000000000000..c4e0b66d4272 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxQueue.cpp @@ -0,0 +1,61 @@ +//===-- LibCxxQueue.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class QueueFrontEnd : public SyntheticChildrenFrontEnd { +public: + QueueFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return m_container_sp ? m_container_sp->GetIndexOfChildWithName(name) + : UINT32_MAX; + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + + size_t CalculateNumChildren() override { + return m_container_sp ? m_container_sp->GetNumChildren() : 0; + } + + ValueObjectSP GetChildAtIndex(size_t idx) override { + return m_container_sp ? m_container_sp->GetChildAtIndex(idx, true) + : nullptr; + } + +private: + ValueObjectSP m_container_sp; +}; +} // namespace + +bool QueueFrontEnd::Update() { + m_container_sp.reset(); + ValueObjectSP c_sp = m_backend.GetChildMemberWithName(ConstString("c"), true); + if (!c_sp) + return false; + m_container_sp = c_sp->GetSyntheticValue(); + return false; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxQueueFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new QueueFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp new file mode 100644 index 000000000000..9b412a12f532 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxTuple.cpp @@ -0,0 +1,83 @@ +//===-- LibCxxTuple.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; + +namespace { + +class TupleFrontEnd: public SyntheticChildrenFrontEnd { +public: + TupleFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { + Update(); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return formatters::ExtractIndexFromString(name.GetCString()); + } + + bool MightHaveChildren() override { return true; } + bool Update() override; + size_t CalculateNumChildren() override { return m_elements.size(); } + ValueObjectSP GetChildAtIndex(size_t idx) override; + +private: + std::vector<ValueObjectSP> m_elements; + ValueObjectSP m_base_sp; +}; +} + +bool TupleFrontEnd::Update() { + m_elements.clear(); + m_base_sp = m_backend.GetChildMemberWithName(ConstString("__base_"), true); + if (! m_base_sp) { + // Pre r304382 name of the base element. + m_base_sp = m_backend.GetChildMemberWithName(ConstString("base_"), true); + } + if (! m_base_sp) + return false; + m_elements.assign(m_base_sp->GetCompilerType().GetNumDirectBaseClasses(), + ValueObjectSP()); + return false; +} + +ValueObjectSP TupleFrontEnd::GetChildAtIndex(size_t idx) { + if (idx >= m_elements.size()) + return ValueObjectSP(); + if (!m_base_sp) + return ValueObjectSP(); + if (m_elements[idx]) + return m_elements[idx]; + + CompilerType holder_type = + m_base_sp->GetCompilerType().GetDirectBaseClassAtIndex(idx, nullptr); + if (!holder_type) + return ValueObjectSP(); + ValueObjectSP holder_sp = m_base_sp->GetChildAtIndex(idx, true); + if (!holder_sp) + return ValueObjectSP(); + + ValueObjectSP elem_sp = holder_sp->GetChildAtIndex(0, true); + if (elem_sp) + m_elements[idx] = + elem_sp->Clone(ConstString(llvm::formatv("[{0}]", idx).str())); + + return m_elements[idx]; +} + +SyntheticChildrenFrontEnd * +formatters::LibcxxTupleFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) { + if (valobj_sp) + return new TupleFrontEnd(*valobj_sp); + return nullptr; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 190b5f64381e..0f1c2537d651 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -121,11 +121,10 @@ lldb::ValueObjectSP lldb_private::formatters:: if (!first_sp) return nullptr; m_element_type = first_sp->GetCompilerType(); - lldb::TemplateArgumentKind kind; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); m_element_type = m_element_type.GetPointeeType(); m_node_type = m_element_type; - m_element_type = m_element_type.GetTemplateArgument(0, kind); + m_element_type = m_element_type.GetTypeTemplateArgument(0); std::string name; m_element_type = m_element_type.GetFieldAtIndex(0, name, nullptr, nullptr, nullptr); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 6f601c9f6ccb..711130639cd2 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -290,8 +290,7 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator( CompilerType type = valobj_sp->GetCompilerType(); if (!type.IsValid() || type.GetNumTemplateArguments() == 0) return nullptr; - TemplateArgumentKind kind; - CompilerType arg_type = type.GetTemplateArgument(0, kind); + CompilerType arg_type = type.GetTypeTemplateArgument(0); if (arg_type.GetTypeName() == ConstString("bool")) return new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp); return new LibcxxStdVectorSyntheticFrontEnd(valobj_sp); diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index e3018a1884be..3e2b7159f894 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -117,11 +117,8 @@ bool LibstdcppMapIteratorSyntheticFrontEnd::Update() { CompilerType my_type(valobj_sp->GetCompilerType()); if (my_type.GetNumTemplateArguments() >= 1) { - TemplateArgumentKind kind; - CompilerType pair_type = my_type.GetTemplateArgument(0, kind); - if (kind != eTemplateArgumentKindType && - kind != eTemplateArgumentKindTemplate && - kind != eTemplateArgumentKindTemplateExpansion) + CompilerType pair_type = my_type.GetTypeTemplateArgument(0); + if (!pair_type) return false; m_pair_type = pair_type; } else diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt index 7cc93c7b0558..95ace3a3633a 100644 --- a/source/Plugins/Language/ObjC/CMakeLists.txt +++ b/source/Plugins/Language/ObjC/CMakeLists.txt @@ -1,3 +1,13 @@ +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 @@ -21,4 +31,6 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN lldbTarget lldbUtility lldbPluginAppleObjCRuntime + + EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS} ) diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index 27cb9558c482..f6d159201951 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -48,11 +48,11 @@ NSArray_Additionals::GetAdditionalSynthetics() { return g_map; } -class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +class NSArrayMSyntheticFrontEndBase : public SyntheticChildrenFrontEnd { public: - NSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + NSArrayMSyntheticFrontEndBase(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd() override = default; + ~NSArrayMSyntheticFrontEndBase() override = default; size_t CalculateNumChildren() override; @@ -78,11 +78,12 @@ protected: CompilerType m_id_type; }; -class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd { +template <typename D32, typename D64> +class GenericNSArrayMSyntheticFrontEnd : public NSArrayMSyntheticFrontEndBase { public: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp); + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayMSyntheticFrontEnd_109() override; + ~GenericNSArrayMSyntheticFrontEnd() override; bool Update() override; @@ -96,6 +97,11 @@ protected: uint64_t GetSize() override; private: + D32 *m_data_32; + D64 *m_data_64; +}; + +namespace Foundation109 { struct DataDescriptor_32 { uint32_t _used; uint32_t _priv1 : 2; @@ -105,7 +111,7 @@ private: uint32_t _priv3; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _priv1 : 2; @@ -115,29 +121,12 @@ private: uint32_t _priv3; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1010() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1010 { struct DataDescriptor_32 { uint32_t _used; uint32_t _offset; @@ -146,7 +135,7 @@ private: uint32_t _priv2; uint32_t _data; }; - + struct DataDescriptor_64 { uint64_t _used; uint64_t _offset; @@ -155,76 +144,86 @@ private: uint32_t _priv2; uint64_t _data; }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayMSyntheticFrontEnd_1400 : public NSArrayMSyntheticFrontEnd { -public: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); - - ~NSArrayMSyntheticFrontEnd_1400() override; - - bool Update() override; - -protected: - lldb::addr_t GetDataAddress() override; - - uint64_t GetUsedCount() override; - - uint64_t GetOffset() override; - - uint64_t GetSize() override; - -private: + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1428 { struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; + uint32_t _used; + uint32_t _offset; + uint32_t _size; + uint32_t _data; }; - + struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; + uint64_t _used; + uint64_t _offset; + uint64_t _size; + uint64_t _data; }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + template <typename PtrType> + struct DataDescriptor { + PtrType _cow; + // __deque + PtrType _data; + uint32_t _offset; + uint32_t _size; + union { + PtrType _mutations; + struct { + uint32_t _muts; + uint32_t _used; + }; + }; + }; + + using NSArrayMSyntheticFrontEnd = + GenericNSArrayMSyntheticFrontEnd< + DataDescriptor<uint32_t>, DataDescriptor<uint64_t>>; + + template <typename DD> + uint64_t + __NSArrayMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, + sizeof(descriptor), error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSArrayMSize_Impl<DataDescriptor<uint32_t>>(process, valobj_addr, + error); + } else { + return __NSArrayMSize_Impl<DataDescriptor<uint64_t>>(process, valobj_addr, + error); + } + } - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; -}; - -class NSArrayISyntheticFrontEnd_1300 : public SyntheticChildrenFrontEnd { -public: - NSArrayISyntheticFrontEnd_1300(lldb::ValueObjectSP valobj_sp); - - ~NSArrayISyntheticFrontEnd_1300() override = default; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - uint64_t m_items; - lldb::addr_t m_data_ptr; - CompilerType m_id_type; -}; +} -class NSArrayISyntheticFrontEnd_1400 : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64, bool Inline> +class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSArrayISyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp); + GenericNSArrayISyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSArrayISyntheticFrontEnd_1400() override; + ~GenericNSArrayISyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -239,25 +238,58 @@ public: private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; - - struct DataDescriptor_32 { - uint32_t used; - uint32_t offset; - uint32_t size; - uint32_t list; - }; - - struct DataDescriptor_64 { - uint64_t used; - uint64_t offset; - uint64_t size; - uint64_t list; - }; - - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + + D32 *m_data_32; + D64 *m_data_64; CompilerType m_id_type; }; + +namespace Foundation1300 { + struct IDD32 { + uint32_t used; + uint32_t list; + }; + + struct IDD64 { + uint64_t used; + uint64_t list; + }; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; +} + +namespace Foundation1430 { + using NSArrayISyntheticFrontEnd = + Foundation1428::NSArrayMSyntheticFrontEnd; +} + +namespace Foundation1436 { + struct IDD32 { + uint32_t used; + uint32_t list; // in Inline cases, this is the first element + }; + + struct IDD64 { + uint64_t used; + uint64_t list; // in Inline cases, this is the first element + }; + + using NSArrayI_TransferSyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, false>; + + using NSArrayISyntheticFrontEnd = + GenericNSArrayISyntheticFrontEnd<IDD32, IDD64, true>; + + using NSFrozenArrayMSyntheticFrontEnd = + Foundation1437::NSArrayMSyntheticFrontEnd; + + uint64_t + __NSFrozenArrayMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + return Foundation1437::__NSArrayMSize(process, valobj_addr, error); + } +} class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -329,6 +361,8 @@ bool lldb_private::formatters::NSArraySummaryProvider( static const ConstString g_NSArrayI("__NSArrayI"); static const ConstString g_NSArrayM("__NSArrayM"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); static const ConstString g_NSArrayCF("__NSCFArray"); @@ -345,11 +379,28 @@ bool lldb_private::formatters::NSArraySummaryProvider( if (error.Fail()) return false; } else if (class_name == g_NSArrayM) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); + Status error; + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSArrayMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + } + if (error.Fail()) + return false; + } else if (class_name == g_NSArrayI_Transfer) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); if (error.Fail()) return false; + } else if (class_name == g_NSFrozenArrayM) { + Status error; + value = Foundation1436::__NSFrozenArrayMSize(*process_sp, valobj_addr, error); + if (error.Fail()) + return false; } else if (class_name == g_NSArrayMLegacy) { Status error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, @@ -395,7 +446,7 @@ bool lldb_private::formatters::NSArraySummaryProvider( return true; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontEndBase( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_id_type() { @@ -411,28 +462,20 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd( } } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - NSArrayMSyntheticFrontEnd_109(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - NSArrayMSyntheticFrontEnd_1010(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), - m_data_64(nullptr) {} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - NSArrayMSyntheticFrontEnd_1400(lldb::ValueObjectSP valobj_sp) - : NSArrayMSyntheticFrontEnd(valobj_sp), m_data_32(nullptr), +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : NSArrayMSyntheticFrontEndBase(valobj_sp), m_data_32(nullptr), m_data_64(nullptr) {} size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren() { +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::CalculateNumChildren() { return GetUsedCount(); } lldb::ValueObjectSP -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetChildAtIndex( size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); @@ -448,69 +491,10 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex( m_exe_ctx_ref, m_id_type); } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() { - ValueObjectSP valobj_sp = m_backend.GetSP(); - m_ptr_size = 0; - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), - error); - } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), - error); - } - if (error.Fail()) - return false; - return false; -} - -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>::Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -528,12 +512,12 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -541,12 +525,13 @@ bool lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren() { +bool +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::MightHaveChildren() { return true; } size_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( +lldb_private::formatters::NSArrayMSyntheticFrontEndBase::GetIndexOfChildWithName( const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); @@ -555,187 +540,59 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName( return idx; } -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109:: - ~NSArrayMSyntheticFrontEnd_109() { +template <typename D32, typename D64> +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + ~GenericNSArrayMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64> lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetDataAddress() { if (!m_data_32 && !m_data_64) return LLDB_INVALID_ADDRESS; return m_data_32 ? m_data_32->_data : m_data_64->_data; } +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetUsedCount() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_used : m_data_64->_used; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_offset : m_data_64->_offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010:: - ~NSArrayMSyntheticFrontEnd_1010() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->_data : m_data_64->_data; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_used : m_data_64->_used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetOffset() { if (!m_data_32 && !m_data_64) return 0; return m_data_32 ? m_data_32->_offset : m_data_64->_offset; } -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->_size : m_data_64->_size; -} - -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400:: - ~NSArrayMSyntheticFrontEnd_1400() { - delete m_data_32; - m_data_32 = nullptr; - delete m_data_64; - m_data_64 = nullptr; -} - -lldb::addr_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetDataAddress() { - if (!m_data_32 && !m_data_64) - return LLDB_INVALID_ADDRESS; - return m_data_32 ? m_data_32->list : m_data_64->list; -} - +template <typename D32, typename D64> uint64_t -lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetUsedCount() { +lldb_private::formatters:: + GenericNSArrayMSyntheticFrontEnd<D32, D64>:: + GenericNSArrayMSyntheticFrontEnd::GetSize() { if (!m_data_32 && !m_data_64) return 0; - return m_data_32 ? m_data_32->used : m_data_64->used; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetOffset() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->offset : m_data_64->offset; -} - -uint64_t lldb_private::formatters::NSArrayMSyntheticFrontEnd_1400::GetSize() { - if (!m_data_32 && !m_data_64) - return 0; - return m_data_32 ? m_data_32->size : m_data_64->size; -} - - -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::NSArrayISyntheticFrontEnd_1300( - lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), - m_items(0), m_data_ptr(0) { - if (valobj_sp) { - CompilerType type = valobj_sp->GetCompilerType(); - if (type) { - ClangASTContext *ast = valobj_sp->GetExecutionContextRef() - .GetTargetSP() - ->GetScratchClangASTContext(); - if (ast) - m_id_type = CompilerType(ast->getASTContext(), - ast->getASTContext()->ObjCBuiltinIdTy); - } - } -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetIndexOfChildWithName( - const ConstString &name) { - const char *item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::CalculateNumChildren() { - return m_items; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::Update() { - m_ptr_size = 0; - m_items = 0; - m_data_ptr = 0; - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - error.Clear(); - lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); - if (!process_sp) - return false; - m_ptr_size = process_sp->GetAddressByteSize(); - uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; - m_items = process_sp->ReadPointerFromMemory(data_location, error); - if (error.Fail()) - return false; - m_data_ptr = data_location + m_ptr_size; - return false; -} - -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::MightHaveChildren() { - return true; -} - -lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1300::GetChildAtIndex( - size_t idx) { - if (idx >= CalculateNumChildren()) - return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_ptr; - object_at_idx += (idx * m_ptr_size); - ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); - if (!process_sp) - return lldb::ValueObjectSP(); - Status error; - if (error.Fail()) - return lldb::ValueObjectSP(); - StreamString idx_name; - idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return CreateValueObjectFromAddress(idx_name.GetString(), object_at_idx, - m_exe_ctx_ref, m_id_type); + return m_data_32 ? m_data_32->_size : m_data_64->_size; } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFrontEnd_1400( +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GenericNSArrayISyntheticFrontEnd( lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_data_32(nullptr), m_data_64(nullptr) { @@ -752,16 +609,19 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::NSArrayISyntheticFront } } -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::~NSArrayISyntheticFrontEnd_1400() { +template <typename D32, typename D64, bool Inline> +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + ~GenericNSArrayISyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithName( - const ConstString &name) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -769,12 +629,17 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetIndexOfChildWithNam return idx; } +template <typename D32, typename D64, bool Inline> size_t -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::CalculateNumChildren() { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + CalculateNumChildren() { return m_data_32 ? m_data_32->used : m_data_64->used; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + Update() { ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; @@ -792,12 +657,12 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { m_ptr_size = process_sp->GetAddressByteSize(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -805,17 +670,29 @@ bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::Update() { return false; } -bool lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::MightHaveChildren() { +template <typename D32, typename D64, bool Inline> +bool +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + MightHaveChildren() { return true; } +template <typename D32, typename D64, bool Inline> lldb::ValueObjectSP -lldb_private::formatters::NSArrayISyntheticFrontEnd_1400::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>:: + GetChildAtIndex(size_t idx) { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); - lldb::addr_t object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + lldb::addr_t object_at_idx; + if (Inline) { + object_at_idx = m_backend.GetSP()->GetValueAsUnsigned(0) + m_ptr_size; + object_at_idx += m_ptr_size == 4 ? sizeof(D32) : sizeof(D64); // skip the data header + object_at_idx -= m_ptr_size; // we treat the last entry in the data header as the first pointer + } else { + object_at_idx = m_data_32 ? m_data_32->list : m_data_64->list; + } object_at_idx += (idx * m_ptr_size); + ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); if (!process_sp) return lldb::ValueObjectSP(); @@ -933,6 +810,8 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( ConstString class_name(descriptor->GetClassName()); static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSArrayI_Transfer("__NSArrayI_Transfer"); + static const ConstString g_NSFrozenArrayM("__NSFrozenArrayM"); static const ConstString g_NSArrayM("__NSArrayM"); static const ConstString g_NSArray0("__NSArray0"); static const ConstString g_NSArray1("__NSSingleObjectArrayI"); @@ -943,21 +822,30 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator( return nullptr; if (class_name == g_NSArrayI) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayISyntheticFrontEnd_1400(valobj_sp)); - else - return (new NSArrayISyntheticFrontEnd_1300(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1436) + return (new Foundation1436::NSArrayISyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1430) + return (new Foundation1430::NSArrayISyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSArrayISyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArrayI_Transfer) { + return (new Foundation1436::NSArrayI_TransferSyntheticFrontEnd(valobj_sp)); + } else if (class_name == g_NSArray0) { + } else if (class_name == g_NSFrozenArrayM) { + return (new Foundation1436::NSFrozenArrayMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray0) { return (new NSArray0SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArray1) { return (new NSArray1SyntheticFrontEnd(valobj_sp)); } else if (class_name == g_NSArrayM) { - if (runtime->GetFoundationVersion() >= 1400) - return (new NSArrayMSyntheticFrontEnd_1400(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSArrayMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp)); if (runtime->GetFoundationVersion() >= 1100) - return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); + return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp)); else - return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); + return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp)); } else { auto &map(NSArray_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name), end = map.end(); diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp index 50febbe39758..c564aa1a8571 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -165,11 +165,12 @@ private: ValueObjectSP m_pair; }; -class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { +template <typename D32, typename D64> +class GenericNSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - ~NSDictionaryMSyntheticFrontEnd() override; + ~GenericNSDictionaryMSyntheticFrontEnd() override; size_t CalculateNumChildren() override; @@ -182,20 +183,6 @@ public: size_t GetIndexOfChildWithName(const ConstString &name) override; private: - struct DataDescriptor_32 { - uint32_t used : 26; - uint32_t kvo : 1; - uint32_t size; - uint32_t buffer; - }; - - struct DataDescriptor_64 { - uint64_t used : 58; - uint32_t kvo : 1; - uint64_t size; - uint64_t buffer; - }; - struct DictionaryItemDescriptor { lldb::addr_t key_ptr; lldb::addr_t val_ptr; @@ -205,61 +192,169 @@ private: ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; + D32 *m_data_32; + D64 *m_data_64; CompilerType m_pair_type; std::vector<DictionaryItemDescriptor> m_children; }; - -class NSDictionaryMLegacySyntheticFrontEnd : public SyntheticChildrenFrontEnd { -public: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); - - ~NSDictionaryMLegacySyntheticFrontEnd() override; - - size_t CalculateNumChildren() override; - - lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - - bool Update() override; - - bool MightHaveChildren() override; - - size_t GetIndexOfChildWithName(const ConstString &name) override; - -private: + +namespace Foundation1100 { + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { + public: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + + ~NSDictionaryMSyntheticFrontEnd() override; + + size_t CalculateNumChildren() override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; + + bool Update() override; + + bool MightHaveChildren() override; + + size_t GetIndexOfChildWithName(const ConstString &name) override; + + private: + struct DataDescriptor_32 { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + + struct DataDescriptor_64 { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + + struct DictionaryItemDescriptor { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + CompilerType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; + }; +} + +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _kvo : 1; uint32_t _size; - uint32_t _mutations; - uint32_t _objs_addr; - uint32_t _keys_addr; + uint32_t _buffer; + uint64_t GetSize() { return _size; } }; - + struct DataDescriptor_64 { uint64_t _used : 58; uint32_t _kvo : 1; uint64_t _size; - uint64_t _mutations; - uint64_t _objs_addr; - uint64_t _keys_addr; + uint64_t _buffer; + uint64_t GetSize() { return _size; } }; - - struct DictionaryItemDescriptor { - lldb::addr_t key_ptr; - lldb::addr_t val_ptr; - lldb::ValueObjectSP valobj_sp; + + + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; +} + +namespace Foundation1437 { + static const uint64_t NSDictionaryCapacities[] = { + 0, 3, 7, 13, 23, 41, 71, 127, 191, 251, 383, 631, 1087, 1723, + 2803, 4523, 7351, 11959, 19447, 31231, 50683, 81919, 132607, + 214519, 346607, 561109, 907759, 1468927, 2376191, 3845119, + 6221311, 10066421, 16287743, 26354171, 42641881, 68996069, + 111638519, 180634607, 292272623, 472907251 + }; + + static const size_t NSDictionaryNumSizeBuckets = sizeof(NSDictionaryCapacities) / sizeof(uint64_t); + + struct DataDescriptor_32 { + uint32_t _buffer; + union { + struct { + uint32_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } }; + + struct DataDescriptor_64 { + uint64_t _buffer; + union { + struct { + uint64_t _mutations; + }; + struct { + uint32_t _muts; + uint32_t _used:25; + uint32_t _kvo:1; + uint32_t _szidx:6; + }; + }; + + uint64_t GetSize() { + return (_szidx) >= NSDictionaryNumSizeBuckets ? + 0 : NSDictionaryCapacities[_szidx]; + } + }; + + using NSDictionaryMSyntheticFrontEnd = + GenericNSDictionaryMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSDictionaryMSize_Impl(lldb_private::Process &process, + lldb::addr_t valobj_addr, Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSDictionaryMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSDictionaryMSize_Impl<DataDescriptor_32>(process, valobj_addr, + error); + } else { + return __NSDictionaryMSize_Impl<DataDescriptor_64>(process, valobj_addr, + error); + } + } - ExecutionContextRef m_exe_ctx_ref; - uint8_t m_ptr_size; - lldb::ByteOrder m_order; - DataDescriptor_32 *m_data_32; - DataDescriptor_64 *m_data_64; - CompilerType m_pair_type; - std::vector<DictionaryItemDescriptor> m_children; -}; +} } // namespace formatters } // namespace lldb_private @@ -313,12 +408,19 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSDictionaryMSize(*process_sp, valobj_addr, + error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (class_name == g_Dictionary1) { value = 1; } @@ -396,13 +498,15 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } else if (class_name == g_DictionaryM) { - if (runtime->GetFoundationVersion() > 1400) { - return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); + if (runtime->GetFoundationVersion() >= 1437) { + return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); + } else if (runtime->GetFoundationVersion() >= 1428) { + return (new Foundation1428::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } } else if (class_name == g_DictionaryMLegacy) { - return (new NSDictionaryMLegacySyntheticFrontEnd(valobj_sp)); + return (new Foundation1100::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else if (class_name == g_Dictionary1) { return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); } else { @@ -641,22 +745,25 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex( return m_pair; } -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GenericNSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - ~NSDictionaryMSyntheticFrontEnd() { +template <typename D32, typename D64> +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + ~GenericNSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -664,14 +771,18 @@ size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: - CalculateNumChildren() { +template <typename D32, typename D64> +size_t +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; - return (m_data_32 ? m_data_32->used : m_data_64->used); + return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -691,12 +802,12 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { m_order = process_sp->GetByteOrder(); uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; if (m_ptr_size == 4) { - m_data_32 = new DataDescriptor_32(); - process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), + m_data_32 = new D32(); + process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), error); } else { - m_data_64 = new DataDescriptor_64(); - process_sp->ReadMemory(data_location, m_data_64, sizeof(DataDescriptor_64), + m_data_64 = new D64(); + process_sp->ReadMemory(data_location, m_data_64, sizeof(D64), error); } if (error.Fail()) @@ -704,24 +815,28 @@ bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMSyntheticFrontEnd:: +template <typename D32, typename D64> +bool +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: MightHaveChildren() { return true; } +template <typename D32, typename D64> lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( +lldb_private::formatters::GenericNSDictionaryMSyntheticFrontEnd<D32,D64>:: + GetChildAtIndex( size_t idx) { lldb::addr_t m_keys_ptr; lldb::addr_t m_values_ptr; if (m_data_32) { - uint32_t size = m_data_32->size; - m_keys_ptr = m_data_32->buffer; - m_values_ptr = m_data_32->buffer + (m_ptr_size * size); + uint32_t size = m_data_32->GetSize(); + m_keys_ptr = m_data_32->_buffer; + m_values_ptr = m_data_32->_buffer + (m_ptr_size * size); } else { - uint32_t size = m_data_64->size; - m_keys_ptr = m_data_64->buffer; - m_values_ptr = m_data_64->buffer + (m_ptr_size * size); + uint32_t size = m_data_64->GetSize(); + m_keys_ptr = m_data_64->_buffer; + m_values_ptr = m_data_64->_buffer + (m_ptr_size * size); } uint32_t num_children = CalculateNumChildren(); @@ -800,22 +915,24 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex( } -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - NSDictionaryMLegacySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd:: + NSDictionaryMSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), m_order(lldb::eByteOrderInvalid), m_data_32(nullptr), m_data_64(nullptr), m_pair_type() {} -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - ~NSDictionaryMLegacySyntheticFrontEnd() { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd() { delete m_data_32; m_data_32 = nullptr; delete m_data_64; m_data_64 = nullptr; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - GetIndexOfChildWithName(const ConstString &name) { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) { const char *item_name = name.GetCString(); uint32_t idx = ExtractIndexFromString(item_name); if (idx < UINT32_MAX && idx >= CalculateNumChildren()) @@ -823,14 +940,17 @@ size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: return idx; } -size_t lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - CalculateNumChildren() { +size_t +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::CalculateNumChildren() { if (!m_data_32 && !m_data_64) return 0; return (m_data_32 ? m_data_32->_used : m_data_64->_used); } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::Update() { m_children.clear(); ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; @@ -863,14 +983,15 @@ bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::Update() { return false; } -bool lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd:: - MightHaveChildren() { +bool +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::MightHaveChildren() { return true; } lldb::ValueObjectSP -lldb_private::formatters::NSDictionaryMLegacySyntheticFrontEnd::GetChildAtIndex( - size_t idx) { +lldb_private::formatters::Foundation1100:: + NSDictionaryMSyntheticFrontEnd::GetChildAtIndex(size_t idx) { lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); lldb::addr_t m_values_ptr = diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp index 2f3398775169..fa2483ecc094 100644 --- a/source/Plugins/Language/ObjC/NSSet.cpp +++ b/source/Plugins/Language/ObjC/NSSet.cpp @@ -135,7 +135,7 @@ namespace Foundation1300 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } -namespace Foundation1400 { +namespace Foundation1428 { struct DataDescriptor_32 { uint32_t _used : 26; uint32_t _size; @@ -154,6 +154,64 @@ namespace Foundation1400 { GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; } +namespace Foundation1437 { + struct DataDescriptor_32 { + uint32_t _cow; + // __table storage + uint32_t _objs_addr; + union { + uint32_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + struct DataDescriptor_64 { + uint64_t _cow; + // __Table storage + uint64_t _objs_addr; + union { + uint64_t _mutations; + struct { + uint32_t _muts; + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + }; + }; + + using NSSetMSyntheticFrontEnd = + GenericNSSetMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>; + + template <typename DD> + uint64_t + __NSSetMSize_Impl(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + const lldb::addr_t start_of_descriptor = + valobj_addr + process.GetAddressByteSize(); + DD descriptor = DD(); + process.ReadMemory(start_of_descriptor, &descriptor, sizeof(descriptor), + error); + if (error.Fail()) { + return 0; + } + return descriptor._used; + } + + uint64_t + __NSSetMSize(lldb_private::Process &process, lldb::addr_t valobj_addr, + Status &error) { + if (process.GetAddressByteSize() == 4) { + return __NSSetMSize_Impl<DataDescriptor_32>(process, valobj_addr, error); + } else { + return __NSSetMSize_Impl<DataDescriptor_64>(process, valobj_addr, error); + } + } +} + class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: NSSetCodeRunningSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); @@ -219,12 +277,18 @@ bool lldb_private::formatters::NSSetSummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } else if (!strcmp(class_name, "__NSSetM")) { + AppleObjCRuntime *apple_runtime = + llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; - value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); + if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1437) { + value = Foundation1437::__NSSetMSize(*process_sp, valobj_addr, error); + } else { + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, + ptr_size, 0, error); + value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); + } if (error.Fail()) return false; - value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } /*else if (!strcmp(class_name,"__NSCFSet")) { @@ -312,10 +376,16 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator( } else if (!strcmp(class_name, "__NSSetM")) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); - if (apple_runtime && apple_runtime->GetFoundationVersion() >= 1400) - return (new Foundation1400::NSSetMSyntheticFrontEnd(valobj_sp)); - else + if (apple_runtime) { + if (apple_runtime->GetFoundationVersion() >= 1437) + return (new Foundation1437::NSSetMSyntheticFrontEnd(valobj_sp)); + else if (apple_runtime->GetFoundationVersion() >= 1428) + return (new Foundation1428::NSSetMSyntheticFrontEnd(valobj_sp)); + else + return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } else { return (new Foundation1300::NSSetMSyntheticFrontEnd(valobj_sp)); + } } else { auto &map(NSSet_Additionals::GetAdditionalSynthetics()); auto iter = map.find(class_name_cs), end = map.end(); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index e99fd74a352f..105c088b9e91 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -324,8 +324,6 @@ public: clang::ASTContext &ast_ctx(interface_decl->getASTContext()); - clang::QualType return_qual_type; - const bool isInstance = instance; const bool isVariadic = false; const bool isSynthesized = false; @@ -653,3 +651,11 @@ AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append, return ret; } + +clang::ExternalASTMerger::ImporterSource +AppleObjCDeclVendor::GetImporterSource() { + return {*m_ast_ctx.getASTContext(), + *m_ast_ctx.getFileManager(), + m_ast_ctx.GetOriginMap() + }; +} diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h index 26824079d945..2f087da16bc1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -30,6 +30,8 @@ public: uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches, std::vector<clang::NamedDecl *> &decls) override; + clang::ExternalASTMerger::ImporterSource GetImporterSource() override; + friend class AppleObjCExternalASTSource; private: diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index 57d98fbd7283..1b22ee4c3be1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -95,6 +95,8 @@ public: virtual void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, lldb::addr_t &cf_false); + + virtual bool IsTaggedPointer (lldb::addr_t addr) { return false; } protected: // Call CreateInstance instead. diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 2a7735959a91..bdf79f7b82bd 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -62,6 +62,11 @@ #include "AppleObjCTrampolineHandler.h" #include "AppleObjCTypeEncodingParser.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" + +#include <vector> + using namespace lldb; using namespace lldb_private; @@ -394,7 +399,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, } bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( - ValueObject &in_value, DynamicValueType use_dynamic, + ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) { // We should never get here with a null process... @@ -811,85 +816,43 @@ UtilityFunction *AppleObjCRuntimeV2::CreateObjectChecker(const char *name) { int len = 0; if (m_has_object_getClass) { - len = ::snprintf(check_function_code, sizeof(check_function_code), - "extern \"C\" void *gdb_object_getClass(void *); " - " \n" - "extern \"C\" int printf(const char *format, ...); " - " \n" - "extern \"C\" void " - " \n" - "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) " - " \n" - "{ " - " \n" - " if ($__lldb_arg_obj == (void *)0) " - " \n" - " return; // nil is ok " - " \n" - " if (!gdb_object_getClass($__lldb_arg_obj)) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " else if ($__lldb_arg_selector != (void *)0) " - " \n" - " { " - " \n" - " signed char responds = (signed char) [(id) " - "$__lldb_arg_obj \n" - " " - "respondsToSelector: \n" - " (struct " - "objc_selector *) $__lldb_arg_selector]; \n" - " if (responds == (signed char) 0) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " } " - " \n" - "} " - " \n", - name); + len = ::snprintf(check_function_code, sizeof(check_function_code), R"( + extern "C" void *gdb_object_getClass(void *); + extern "C" int printf(const char *format, ...); + extern "C" void + %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { + if ($__lldb_arg_obj == (void *)0) + return; // nil is ok + if (!gdb_object_getClass($__lldb_arg_obj)) { + *((volatile int *)0) = 'ocgc'; + } else if ($__lldb_arg_selector != (void *)0) { + signed char $responds = (signed char) + [(id)$__lldb_arg_obj respondsToSelector: + (void *) $__lldb_arg_selector]; + if ($responds == (signed char) 0) + *((volatile int *)0) = 'ocgc'; + } + })", name); } else { - len = ::snprintf(check_function_code, sizeof(check_function_code), - "extern \"C\" void *gdb_class_getClass(void *); " - " \n" - "extern \"C\" int printf(const char *format, ...); " - " \n" - "extern \"C\" void " - " \n" - "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) " - " \n" - "{ " - " \n" - " if ($__lldb_arg_obj == (void *)0) " - " \n" - " return; // nil is ok " - " \n" - " void **$isa_ptr = (void **)$__lldb_arg_obj; " - " \n" - " if (*$isa_ptr == (void *)0 || " - "!gdb_class_getClass(*$isa_ptr)) \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " else if ($__lldb_arg_selector != (void *)0) " - " \n" - " { " - " \n" - " signed char responds = (signed char) [(id) " - "$__lldb_arg_obj \n" - " " - "respondsToSelector: \n" - " (struct " - "objc_selector *) $__lldb_arg_selector]; \n" - " if (responds == (signed char) 0) " - " \n" - " *((volatile int *)0) = 'ocgc'; " - " \n" - " } " - " \n" - "} " - " \n", - name); + len = ::snprintf(check_function_code, sizeof(check_function_code), R"( + extern "C" void *gdb_class_getClass(void *); + extern "C" int printf(const char *format, ...); + extern "C" void + %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { + if ($__lldb_arg_obj == (void *)0) + return; // nil is ok + void **$isa_ptr = (void **)$__lldb_arg_obj; + if (*$isa_ptr == (void *)0 || + !gdb_class_getClass(*$isa_ptr)) + *((volatile int *)0) = 'ocgc'; + else if ($__lldb_arg_selector != (void *)0) { + signed char $responds = (signed char) + [(id)$__lldb_arg_obj respondsToSelector: + (void *) $__lldb_arg_selector]; + if ($responds == (signed char) 0) + *((volatile int *)0) = 'ocgc'; + } + })", name); } assert(len < (int)sizeof(check_function_code)); @@ -2022,6 +1985,8 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( Status error; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); if (error.Fail()) @@ -2038,12 +2003,47 @@ AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( if (error.Fail()) return NULL; + if (log) + log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); + + bool foundError = false; + auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp, + error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_magic_value"), + objc_module_sp, error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp, + error); + foundError |= error.Fail(); + + auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_indexed_isa_index_shift"), + objc_module_sp, error); + foundError |= error.Fail(); + + auto objc_indexed_classes = + ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"), + objc_module_sp, error, false); + foundError |= error.Fail(); + + if (log) + log->PutCString("AOCRT::NPI: Found all the indexed ISA masks"); + // we might want to have some rules to outlaw these other values (e.g if the // mask is zero but the value is non-zero, ...) - return new NonPointerISACache(runtime, objc_debug_isa_class_mask, - objc_debug_isa_magic_mask, - objc_debug_isa_magic_value); + return new NonPointerISACache( + runtime, objc_module_sp, objc_debug_isa_class_mask, + objc_debug_isa_magic_mask, objc_debug_isa_magic_value, + objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value, + objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift, + foundError ? 0 : objc_indexed_classes); } AppleObjCRuntimeV2::TaggedPointerVendorV2 * @@ -2371,12 +2371,23 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( } AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache( - AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_isa_class_mask, - uint64_t objc_debug_isa_magic_mask, uint64_t objc_debug_isa_magic_value) - : m_runtime(runtime), m_cache(), + AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp, + uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, + uint64_t objc_debug_isa_magic_value, + uint64_t objc_debug_indexed_isa_magic_mask, + uint64_t objc_debug_indexed_isa_magic_value, + uint64_t objc_debug_indexed_isa_index_mask, + uint64_t objc_debug_indexed_isa_index_shift, + lldb::addr_t objc_indexed_classes) + : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp), m_objc_debug_isa_class_mask(objc_debug_isa_class_mask), m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask), - m_objc_debug_isa_magic_value(objc_debug_isa_magic_value) {} + m_objc_debug_isa_magic_value(objc_debug_isa_magic_value), + m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask), + m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value), + m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask), + m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift), + m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {} ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { @@ -2395,8 +2406,106 @@ AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( ObjCISA isa, ObjCISA &ret_isa) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + + if (log) + log->Printf("AOCRT::NPI Evalulate(isa = 0x%" PRIx64 ")", (uint64_t)isa); + if ((isa & ~m_objc_debug_isa_class_mask) == 0) return false; + + // If all of the indexed ISA variables are set, then its possible that + // this ISA is indexed, and we should first try to get its value using + // the index. + // Note, we check these varaibles first as the ObjC runtime will set at + // least one of their values to 0 if they aren't needed. + if (m_objc_debug_indexed_isa_magic_mask && + m_objc_debug_indexed_isa_magic_value && + m_objc_debug_indexed_isa_index_mask && + m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) { + if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0) + return false; + + if ((isa & m_objc_debug_indexed_isa_magic_mask) == + m_objc_debug_indexed_isa_magic_value) { + // Magic bits are correct, so try extract the index. + uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >> + m_objc_debug_indexed_isa_index_shift; + // If the index is out of bounds of the length of the array then + // check if the array has been updated. If that is the case then + // we should try read the count again, and update the cache if the + // count has been updated. + if (index > m_indexed_isa_cache.size()) { + if (log) + log->Printf("AOCRT::NPI (index = %" PRIu64 + ") exceeds cache (size = %" PRIu64 ")", + (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); + + Process *process(m_runtime.GetProcess()); + + ModuleSP objc_module_sp(m_objc_module_wp.lock()); + if (!objc_module_sp) + return false; + + Status error; + auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol( + process, ConstString("objc_indexed_classes_count"), objc_module_sp, + error); + if (error.Fail()) + return false; + + if (log) + log->Printf("AOCRT::NPI (new class count = %" PRIu64 ")", + (uint64_t)objc_indexed_classes_count); + + if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { + // Read the class entries we don't have. We should just + // read all of them instead of just the one we need as then + // we can cache those we may need later. + auto num_new_classes = + objc_indexed_classes_count - m_indexed_isa_cache.size(); + const uint32_t addr_size = process->GetAddressByteSize(); + DataBufferHeap buffer(num_new_classes * addr_size, 0); + + lldb::addr_t last_read_class = + m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size); + size_t bytes_read = process->ReadMemory( + last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error); + if (error.Fail() || bytes_read != buffer.GetByteSize()) + return false; + + if (log) + log->Printf("AOCRT::NPI (read new classes count = %" PRIu64 ")", + (uint64_t)num_new_classes); + + // Append the new entries to the existing cache. + DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), + process->GetByteOrder(), + process->GetAddressByteSize()); + + lldb::offset_t offset = 0; + for (unsigned i = 0; i != num_new_classes; ++i) + m_indexed_isa_cache.push_back(data.GetPointer(&offset)); + } + } + + // If the index is still out of range then this isn't a pointer. + if (index > m_indexed_isa_cache.size()) + return false; + + if (log) + log->Printf("AOCRT::NPI Evalulate(ret_isa = 0x%" PRIx64 ")", + (uint64_t)m_indexed_isa_cache[index]); + + ret_isa = m_indexed_isa_cache[index]; + return (ret_isa != 0); // this is a pointer so 0 is not a valid value + } + + return false; + } + + // Definately not an indexed ISA, so try to use a mask to extract + // the pointer from the ISA. if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) { ret_isa = isa & m_objc_debug_isa_class_mask; return (ret_isa != 0); // this is a pointer so 0 is not a valid value diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 718073090406..89e81d5b181e 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -88,6 +88,8 @@ public: EncodingToTypeSP GetEncodingToType() override; + bool IsTaggedPointer(lldb::addr_t ptr) override; + TaggedPointerVendor *GetTaggedPointerVendor() override { return m_tagged_pointer_vendor_ap.get(); } @@ -138,18 +140,33 @@ private: private: NonPointerISACache(AppleObjCRuntimeV2 &runtime, + const lldb::ModuleSP &objc_module_sp, uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, - uint64_t objc_debug_isa_magic_value); + uint64_t objc_debug_isa_magic_value, + uint64_t objc_debug_indexed_isa_magic_mask, + uint64_t objc_debug_indexed_isa_magic_value, + uint64_t objc_debug_indexed_isa_index_mask, + uint64_t objc_debug_indexed_isa_index_shift, + lldb::addr_t objc_indexed_classes); bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa); AppleObjCRuntimeV2 &m_runtime; std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache; + lldb::ModuleWP m_objc_module_wp; uint64_t m_objc_debug_isa_class_mask; uint64_t m_objc_debug_isa_magic_mask; uint64_t m_objc_debug_isa_magic_value; + uint64_t m_objc_debug_indexed_isa_magic_mask; + uint64_t m_objc_debug_indexed_isa_magic_value; + uint64_t m_objc_debug_indexed_isa_index_mask; + uint64_t m_objc_debug_indexed_isa_index_shift; + lldb::addr_t m_objc_indexed_classes; + + std::vector<lldb::addr_t> m_indexed_isa_cache; + friend class AppleObjCRuntimeV2; DISALLOW_COPY_AND_ASSIGN(NonPointerISACache); @@ -279,8 +296,6 @@ private: ObjCISA GetPointerISA(ObjCISA isa); - bool IsTaggedPointer(lldb::addr_t ptr); - lldb::addr_t GetISAHashTablePointer(); bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table); diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 7e46afcccdab..ad1083be0285 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -3615,13 +3615,15 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) { } BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName("RenderScriptKernel", err)) + target.AddNameToBreakpoint(bp, "RenderScriptKernel", err); + if (err.Fail() && log) if (log) log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString()); @@ -3643,14 +3645,15 @@ RenderScriptRuntime::CreateReductionBreakpoint(const ConstString &name, BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver( nullptr, name, &m_rsmodules, kernel_types)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName("RenderScriptReduction", err)) - if (log) + target.AddNameToBreakpoint(bp, "RenderScriptReduction", err); + if (err.Fail() && log) log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString()); @@ -3885,15 +3888,16 @@ RenderScriptRuntime::CreateScriptGroupBreakpoint(const ConstString &name, BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver( nullptr, name, m_scriptGroups, stop_on_all)); - BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint( + Target &target = GetProcess()->GetTarget(); + BreakpointSP bp = target.CreateBreakpoint( m_filtersp, resolver_sp, false, false, false); // Give RS breakpoints a specific name, so the user can manipulate them as a // group. Status err; - if (!bp->AddName(name.AsCString(), err)) - if (log) - log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, - err.AsCString()); + target.AddNameToBreakpoint(bp, name.GetCString(), err); + if (err.Fail() && log) + log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, + err.AsCString()); // ask the breakpoint to resolve itself bp->ResolveBreakpoint(); return bp; diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 25bfce7a2b83..d7bef836d9d8 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -27,12 +27,12 @@ typedef struct ar_hdr { #include <ar.h> #endif -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index 0e10d47f2ce4..cb63eccff65e 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -10,10 +10,9 @@ #ifndef liblldb_ObjectContainerBSDArchive_h_ #define liblldb_ObjectContainerBSDArchive_h_ -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index 31eb17873f3e..0266bbe27e7d 100644 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -8,12 +8,12 @@ //===----------------------------------------------------------------------===// #include "ObjectContainerUniversalMachO.h" -#include "lldb/Core/ArchSpec.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" diff --git a/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/source/Plugins/ObjectFile/ELF/CMakeLists.txt index e0680b07efc5..45a4edcbb1c9 100644 --- a/source/Plugins/ObjectFile/ELF/CMakeLists.txt +++ b/source/Plugins/ObjectFile/ELF/CMakeLists.txt @@ -9,5 +9,6 @@ add_lldb_library(lldbPluginObjectFileELF PLUGIN lldbTarget LINK_COMPONENTS BinaryFormat + Object Support ) diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 3b33cf1601fb..17d892450e4d 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -13,7 +13,6 @@ #include <cassert> #include <unordered_map> -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,8 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" @@ -31,6 +32,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" @@ -405,7 +407,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, lldb::offset_t length) { if (!data_sp) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -423,7 +425,7 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -451,7 +453,7 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance( if (ELFHeader::MagicBytesMatch(magic)) { unsigned address_size = ELFHeader::AddressSizeInBytes(magic); if (address_size == 4 || address_size == 8) { - std::auto_ptr<ObjectFileELF> objfile_ap( + std::unique_ptr<ObjectFileELF> objfile_ap( new ObjectFileELF(module_sp, data_sp, process_sp, header_addr)); ArchSpec spec; if (objfile_ap->GetArchitecture(spec) && @@ -1818,6 +1820,12 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (!m_sections_ap.get() && ParseSectionHeaders()) { m_sections_ap.reset(new SectionList()); + // Object files frequently have 0 for every section address, meaning we + // need to compute synthetic addresses in order for "file addresses" from + // different sections to not overlap + bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile); + uint64_t nextaddr = 0; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { const ELFSectionHeaderInfo &header = *I; @@ -1835,6 +1843,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev"); static ConstString g_sect_name_dwarf_debug_addr(".debug_addr"); static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges"); + static ConstString g_sect_name_dwarf_debug_cu_index(".debug_cu_index"); 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"); @@ -1904,6 +1913,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { sect_type = eSectionTypeDWARFDebugAddr; else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges; + else if (name == g_sect_name_dwarf_debug_cu_index) + sect_type = eSectionTypeDWARFDebugCuIndex; else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame; else if (name == g_sect_name_dwarf_debug_info) @@ -1987,9 +1998,18 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { ? m_arch_spec.GetDataByteSize() : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize() : 1; - elf::elf_xword log2align = (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign); + + uint64_t addr = header.sh_addr; + + if ((header.sh_flags & SHF_ALLOC) && synthaddrs) { + nextaddr = + (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1); + addr = nextaddr; + nextaddr += vm_size; + } + SectionSP section_sp(new Section( GetModule(), // Module to which this section belongs. this, // ObjectFile to which this section belongs and should read @@ -1997,7 +2017,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { SectionIndex(I), // Section ID. name, // Section name. sect_type, // Section type. - header.sh_addr, // VM address. + addr, // VM address. vm_size, // VM size in bytes of this section. header.sh_offset, // Offset of this section in the file. file_size, // Size of the section as found in the file. @@ -2015,13 +2035,14 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { if (m_sections_ap.get()) { if (GetType() == eTypeDebugInfo) { static const SectionType g_sections[] = { - eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, - eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame, - eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine, - eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo, - eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes, - eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr, - eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable, + eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr, + eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex, + eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets, + eSectionTypeELFSymbolTable, }; SectionList *elf_section_list = m_sections_ap.get(); for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); @@ -2714,7 +2735,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id, rel_data, symtab_data, strtab_data); } -unsigned ObjectFileELF::RelocateSection( +unsigned ObjectFileELF::ApplyRelocations( Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr, const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr, DataExtractor &rel_data, DataExtractor &symtab_data, @@ -2745,6 +2766,14 @@ unsigned ObjectFileELF::RelocateSection( case R_386_32: case R_386_PC32: default: + // FIXME: This asserts with this input: + // + // foo.cpp + // int main(int argc, char **argv) { return 0; } + // + // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o + // + // and running this on the foo.o module. assert(false && "unexpected relocation type"); } } else { @@ -2791,7 +2820,8 @@ unsigned ObjectFileELF::RelocateSection( } unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, - user_id_t rel_id) { + user_id_t rel_id, + lldb_private::Symtab *thetab) { assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL); // Parse in the section list if needed. @@ -2827,10 +2857,11 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, DataExtractor symtab_data; DataExtractor debug_data; - if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) && - ReadSectionData(debug, debug_data)) { - RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, - debug_hdr, rel_data, symtab_data, debug_data, debug); + if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) && + GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) && + GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) { + ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr, + rel_data, symtab_data, debug_data, debug); } return 0; @@ -2924,21 +2955,48 @@ Symtab *ObjectFileELF::GetSymtab() { m_symtab_ap->CalculateSymbolSizes(); } + return m_symtab_ap.get(); +} + +void ObjectFileELF::RelocateSection(lldb_private::Section *section) +{ + static const char *debug_prefix = ".debug"; + + // Set relocated bit so we stop getting called, regardless of + // whether we actually relocate. + section->SetIsRelocated(true); + + // We only relocate in ELF relocatable files + if (CalculateType() != eTypeObjectFile) + return; + + const char *section_name = section->GetName().GetCString(); + // Can't relocate that which can't be named + if (section_name == nullptr) + return; + + // We don't relocate non-debug sections at the moment + if (strncmp(section_name, debug_prefix, strlen(debug_prefix))) + return; + + // Relocation section names to look for + std::string needle = std::string(".rel") + section_name; + std::string needlea = std::string(".rela") + section_name; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) { - if (CalculateType() == eTypeObjectFile) { - const char *section_name = I->section_name.AsCString(""); - if (strstr(section_name, ".rela.debug") || - strstr(section_name, ".rel.debug")) { - const ELFSectionHeader &reloc_header = *I; - user_id_t reloc_id = SectionIndex(I); - RelocateDebugSections(&reloc_header, reloc_id); - } + const char *hay_name = I->section_name.GetCString(); + if (hay_name == nullptr) + continue; + if (needle == hay_name || needlea == hay_name) { + const ELFSectionHeader &reloc_header = *I; + user_id_t reloc_id = SectionIndex(I); + RelocateDebugSections(&reloc_header, reloc_id, GetSymtab()); + break; } } } - return m_symtab_ap.get(); } void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, @@ -3404,3 +3462,56 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() { } return eStrataUnknown; } + +size_t ObjectFileELF::ReadSectionData(Section *section, + lldb::offset_t section_offset, void *dst, + size_t dst_len) { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_offset, + dst, dst_len); + + if (!section->Test(SHF_COMPRESSED)) + return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len); + + // For compressed sections we need to read to full data to be able to + // decompress. + DataExtractor data; + ReadSectionData(section, data); + return data.CopyData(section_offset, dst_len, dst); +} + +size_t ObjectFileELF::ReadSectionData(Section *section, + DataExtractor §ion_data) { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_data); + + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES); + + size_t result = ObjectFile::ReadSectionData(section, section_data); + if (result == 0 || !section->Test(SHF_COMPRESSED)) + return result; + + auto Decompressor = llvm::object::Decompressor::create( + section->GetName().GetStringRef(), + {reinterpret_cast<const char *>(section_data.GetDataStart()), + size_t(section_data.GetByteSize())}, + GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8); + if (!Decompressor) { + LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}", + section->GetName(), llvm::toString(Decompressor.takeError())); + return result; + } + auto buffer_sp = + std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0); + if (auto Error = Decompressor->decompress( + {reinterpret_cast<char *>(buffer_sp->GetBytes()), + size_t(buffer_sp->GetByteSize())})) { + LLDB_LOG(log, "Decompression of section {0} failed: {1}", + section->GetName(), llvm::toString(std::move(Error))); + return result; + } + section_data.SetData(buffer_sp); + return buffer_sp->GetByteSize(); +} diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 6d8717b0ef25..2909f4e52e4a 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -16,10 +16,8 @@ // C++ Includes #include <vector> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/UUID.h" #include "lldb/lldb-private.h" @@ -142,6 +140,13 @@ public: ObjectFile::Strata CalculateStrata() override; + size_t ReadSectionData(lldb_private::Section *section, + lldb::offset_t section_offset, void *dst, + size_t dst_len) override; + + size_t ReadSectionData(lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) override; + // Returns number of program headers found in the ELF file. size_t GetProgramHeaderCount(); @@ -154,6 +159,8 @@ public: llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; + void RelocateSection(lldb_private::Section *section) override; + private: ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, @@ -296,17 +303,18 @@ private: /// Relocates debug sections unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, - lldb::user_id_t rel_id); - - unsigned RelocateSection(lldb_private::Symtab *symtab, - const elf::ELFHeader *hdr, - const elf::ELFSectionHeader *rel_hdr, - const elf::ELFSectionHeader *symtab_hdr, - const elf::ELFSectionHeader *debug_hdr, - lldb_private::DataExtractor &rel_data, - lldb_private::DataExtractor &symtab_data, - lldb_private::DataExtractor &debug_data, - lldb_private::Section *rel_section); + lldb::user_id_t rel_id, + lldb_private::Symtab *thetab); + + unsigned ApplyRelocations(lldb_private::Symtab *symtab, + const elf::ELFHeader *hdr, + const elf::ELFSectionHeader *rel_hdr, + const elf::ELFSectionHeader *symtab_hdr, + const elf::ELFSectionHeader *debug_hdr, + lldb_private::DataExtractor &rel_data, + lldb_private::DataExtractor &symtab_data, + lldb_private::DataExtractor &debug_data, + lldb_private::Section *rel_section); /// Loads the section name string table into m_shstr_data. Returns the /// number of bytes constituting the table. diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index 06406c6f1655..a9ab366fbf53 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -10,8 +10,6 @@ #include "llvm/ADT/StringRef.h" #include "ObjectFileJIT.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" @@ -26,6 +24,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBuffer.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" @@ -230,9 +229,9 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value, return num_loaded_sections > 0; } -size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section, +size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const { + size_t dst_len) { lldb::offset_t file_size = section->GetFileSize(); if (section_offset < file_size) { size_t src_len = file_size - section_offset; @@ -248,8 +247,8 @@ size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section, } size_t ObjectFileJIT::ReadSectionData( - const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const { + lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) { if (section->GetFileSize()) { const void *src = (void *)(uintptr_t)section->GetFileOffset(); diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index a211645d5d8b..c964906a5e8e 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -83,13 +83,13 @@ public: uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; - size_t ReadSectionData(const lldb_private::Section *section, + size_t ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const override; + size_t dst_len) override; size_t - ReadSectionData(const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const override; + ReadSectionData(lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) override; lldb_private::Address GetEntryPointAddress() override; diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9bc171e454c9..df334f88ee3b 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -17,7 +17,6 @@ #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/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" @@ -38,6 +37,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadList.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -686,7 +686,7 @@ public: 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 && + 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); @@ -1200,6 +1200,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) { case eSectionTypeDWARFDebugAbbrev: case eSectionTypeDWARFDebugAddr: case eSectionTypeDWARFDebugAranges: + case eSectionTypeDWARFDebugCuIndex: case eSectionTypeDWARFDebugFrame: case eSectionTypeDWARFDebugInfo: case eSectionTypeDWARFDebugLine: diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 5607a71ad5aa..72b1b15f08f8 100644 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -10,9 +10,6 @@ #include "ObjectFilePECOFF.h" #include "WindowsMiniDump.h" -#include "llvm/BinaryFormat/COFF.h" - -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -23,12 +20,14 @@ #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/DataBufferLLVM.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Support/MemoryBuffer.h" @@ -136,6 +135,11 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( 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)); + } } } } @@ -537,7 +541,8 @@ Symtab *ObjectFilePECOFF::GetSymtab() { // 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 = (uint32_t *)strtab_data.GetDataStart(); + uint32_t *strtab_data_start = const_cast<uint32_t *>( + reinterpret_cast<const uint32_t *>(strtab_data.GetDataStart())); strtab_data_start[0] = 0; offset = 0; diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 588f3f7aec64..b71f3cf04c33 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -17,7 +17,6 @@ #include "Plugins/Process/Utility/RegisterContextDummy.h" #include "Plugins/Process/Utility/RegisterContextMemory.h" #include "Plugins/Process/Utility/ThreadMemory.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp index d3bcee6f487d..6e15eb2b1dcb 100644 --- a/source/Plugins/Platform/Android/AdbClient.cpp +++ b/source/Plugins/Platform/Android/AdbClient.cpp @@ -46,7 +46,7 @@ using namespace std::chrono; namespace { -const seconds kReadTimeout(12); +const seconds kReadTimeout(20); const char *kOKAY = "OKAY"; const char *kFAIL = "FAIL"; const char *kDATA = "DATA"; diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index 0f37da60d5d6..5b85bcdf7fdd 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -21,6 +21,7 @@ #include "AdbClient.h" #include "PlatformAndroid.h" #include "PlatformAndroidRemoteGDBServer.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -366,9 +367,22 @@ bool PlatformAndroid::GetRemoteOSVersion() { return m_major_os_version != 0; } -llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { +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 (GetSdkVersion() < 26) + 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"); @@ -376,7 +390,7 @@ llvm::StringRef PlatformAndroid::GetLibdlFunctionDeclarations() { extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; - return PlatformPOSIX::GetLibdlFunctionDeclarations(); + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); } AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) { diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h index 638dba973369..4c12eb8c016d 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/source/Plugins/Platform/Android/PlatformAndroid.h @@ -76,7 +76,8 @@ protected: Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, const FileSpec &dst_file_spec) override; - llvm::StringRef GetLibdlFunctionDeclarations() override; + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; private: AdbClient::SyncService *GetSyncService(Status &error); diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 53cec45f986e..73c7d21f0a06 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -314,13 +314,19 @@ void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformFreeBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformFreeBSD::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; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + if (arch.GetTriple().getArch() == llvm::Triple::x86) + args.push_back(0); + return args; } diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index 4bde2148a4d4..274304834290 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -61,8 +61,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) 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(PlatformFreeBSD); diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp index 0bf00ea30798..8186eae0e8c4 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -372,7 +372,7 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, // 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 != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); LLDB_LOG(log, "hooked up STDIO pty to process"); } else @@ -390,8 +390,10 @@ void PlatformLinux::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +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; @@ -406,6 +408,8 @@ uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= map_anon; - return flags_platform; + + 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 index bc7b723427f8..50d721f7c072 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.h +++ b/source/Plugins/Platform/Linux/PlatformLinux.h @@ -59,8 +59,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) 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); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp index 0197d27e76ef..a216e3839dd9 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp @@ -206,7 +206,7 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess( // 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 != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); } } diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp index 52188eefb366..e0558f8b200e 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp index b9f493294a03..9b2608f68625 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -23,6 +22,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index f87852ed7f44..b39aa103f1db 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -1132,28 +1132,33 @@ bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx, 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]; FileSpec temp_file_spec; + + // Get the lldb framework's file path, and if it exists, truncate some + // components to only the developer directory path. if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, 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) { - ::snprintf(shared_frameworks, - sizeof(developer_dir_path) - - (shared_frameworks - developer_dir_path), - "/Developer"); + 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 { - char *lib_priv_frameworks = strstr( - developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework"); - if (lib_priv_frameworks) { - *lib_priv_frameworks = '\0'; + // 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; } } diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp index f168fb6fda5e..e5d27fc28949 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -18,7 +18,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -31,6 +30,7 @@ #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" @@ -694,7 +694,16 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Second look through the kext binarys without dSYMs + // 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(); @@ -739,7 +748,17 @@ Status PlatformDarwinKernel::GetSharedModule( } } } - // Second try all kernel binaries that don't have a dSYM + + // 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 (possible_kernel.Exists()) { ModuleSpec kern_spec(possible_kernel); @@ -767,11 +786,7 @@ Status PlatformDarwinKernel::GetSharedModule( } } - // Else fall back to treating the file's path as an actual file path - defer - // to PlatformDarwin's GetSharedModule. - return PlatformDarwin::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); + return error; } Status PlatformDarwinKernel::ExamineKextForMatchingUUID( diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp index 38facc4aa124..1eef643d3904 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp @@ -17,7 +17,6 @@ #include "PlatformRemoteAppleTV.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -25,6 +24,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp index bbd8f1698937..17ae67bc28de 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp @@ -17,7 +17,6 @@ #include "PlatformRemoteAppleWatch.h" #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -25,6 +24,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index ea44714a916e..cb064aad6155 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index c52b636c8496..5bff792525bc 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -22,6 +21,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp index 3037dd854be7..ee1f90311e7e 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp @@ -15,7 +15,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -24,6 +23,7 @@ #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" diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm index 6a49b645c1e1..7bd37683d2fd 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm @@ -22,7 +22,6 @@ #include "llvm/ADT/StringRef.h" using namespace lldb_private; -using namespace lldb_utility; // 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 diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 9df5b9fac380..38bdf60c1ced 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -393,7 +393,7 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess( // 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 != lldb_utility::PseudoTerminal::invalid_fd) { + if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); if (log) log->Printf("PlatformNetBSD::%s pid %" PRIu64 @@ -420,13 +420,17 @@ void PlatformNetBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformNetBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformNetBSD::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; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h index b1aaa4ab5f59..28a5d6713dd9 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -59,8 +59,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) 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(PlatformNetBSD); diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index edb8ec951d37..050639aba7cc 100644 --- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -133,7 +133,7 @@ PlatformOpenBSD::PlatformOpenBSD(bool is_host) PlatformOpenBSD::~PlatformOpenBSD() = default; bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, - ArchSpec &arch) { + ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSOpenBSD()) { @@ -211,13 +211,17 @@ void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() { m_trap_handlers.push_back(ConstString("_sigtramp")); } -uint64_t PlatformOpenBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) { +MmapArgList PlatformOpenBSD::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; if (flags & eMmapFlagsPrivate) flags_platform |= MAP_PRIVATE; if (flags & eMmapFlagsAnon) flags_platform |= MAP_ANON; - return flags_platform; + + MmapArgList args({addr, length, prot, flags_platform, fd, offset}); + return args; } diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h index 55f6451e236e..cb5e9bfe6392 100644 --- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h +++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h @@ -53,8 +53,10 @@ public: void CalculateTrapHandlerSymbolNames() override; - uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch, - unsigned flags) 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(PlatformOpenBSD); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 013c33def13b..d45a54ee2499 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -944,7 +944,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process, the_result; )", path); - llvm::StringRef prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); lldb::ValueObjectSP result_valobj_sp; error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -992,7 +992,7 @@ Status PlatformPOSIX::UnloadImage(lldb_private::Process *process, StreamString expr; expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); - llvm::StringRef prefix = GetLibdlFunctionDeclarations(); + llvm::StringRef prefix = GetLibdlFunctionDeclarations(process); lldb::ValueObjectSP result_valobj_sp; Status error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); @@ -1024,7 +1024,8 @@ lldb::ProcessSP PlatformPOSIX::ConnectProcess(llvm::StringRef connect_url, error); } -llvm::StringRef PlatformPOSIX::GetLibdlFunctionDeclarations() { +llvm::StringRef +PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) { return R"( extern "C" void* dlopen(const char*, int); extern "C" void* dlsym(void*, const char*); diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index ebc36c2461db..93bebeb332ca 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -201,7 +201,8 @@ protected: llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp); - virtual llvm::StringRef GetLibdlFunctionDeclarations(); + virtual + llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process); private: DISALLOW_COPY_AND_ASSIGN(PlatformPOSIX); diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp index c6daf6ccea6e..6b3d5f6c117f 100644 --- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp +++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp @@ -144,7 +144,7 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[], // Use a fork that ties the child process's stdin/out/err to a pseudo // terminal so we can read it in our MachProcess::STDIOThread // as unbuffered io. - lldb_utility::PseudoTerminal pty; + PseudoTerminal pty; char fork_error[256]; memset(fork_error, 0, sizeof(fork_error)); *pid = static_cast<::pid_t>(pty.Fork(fork_error, sizeof(fork_error))); diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp index 7d956dfc6506..9f5920753d68 100644 --- a/source/Plugins/Process/Darwin/MachException.cpp +++ b/source/Plugins/Process/Darwin/MachException.cpp @@ -57,11 +57,6 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity( extern "C" boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); -// Any access to the g_message variable should be done by locking the -// g_message_mutex first, using the g_message variable, then unlocking -// the g_message_mutex. See MachException::Message::CatchExceptionRaise() -// for sample code. - static MachException::Data *g_message = NULL; extern "C" kern_return_t catch_mach_exception_raise_state( @@ -131,33 +126,6 @@ catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port, return KERN_FAILURE; } -#if 0 -void -MachException::Message::Dump(Stream &stream) const -{ - stream.Printf("exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = " - "0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x " - "id = 0x%8.8x }\n", - exc_msg.hdr.msgh_bits, - exc_msg.hdr.msgh_size, - exc_msg.hdr.msgh_remote_port, - exc_msg.hdr.msgh_local_port, - exc_msg.hdr.msgh_reserved, - exc_msg.hdr.msgh_id); - - stream.Printf("reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port " - "= 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x " - "id = 0x%8.8x }", - reply_msg.hdr.msgh_bits, - reply_msg.hdr.msgh_size, - reply_msg.hdr.msgh_remote_port, - reply_msg.hdr.msgh_local_port, - reply_msg.hdr.msgh_reserved, - reply_msg.hdr.msgh_id); - stream.Flush(); -} -#endif - bool MachException::Data::GetStopInfo(struct ThreadStopInfo *stop_info, const UnixSignals &signals, Stream &stream) const { @@ -279,9 +247,6 @@ void MachException::Message::Dump(Stream &stream) const { bool MachException::Message::CatchExceptionRaise(task_t task) { bool success = false; - // locker will keep a mutex locked until it goes out of scope - // PThreadMutex::Locker locker(&g_message_mutex); - // DNBLogThreaded("calling mach_exc_server"); state.task_port = task; g_message = &state; // The exc_server function is the MIG generated server handling function diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/source/Plugins/Process/Darwin/NativeProcessDarwin.h index 2214bbc52ca4..649280c17a8f 100644 --- a/source/Plugins/Process/Darwin/NativeProcessDarwin.h +++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.h @@ -22,12 +22,12 @@ #include <unordered_set> // Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Host/Debug.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/Pipe.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "lldb/lldb-types.h" @@ -197,20 +197,6 @@ private: // waitpid reader callback handle. MainLoop::ReadHandleUP m_waitpid_reader_handle; -#if 0 - ArchSpec m_arch; - - LazyBool m_supports_mem_region; - std::vector<MemoryRegionInfo> m_mem_region_cache; - - lldb::tid_t m_pending_notification_tid; - - // 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; -#endif - // ----------------------------------------------------------------- // Private Instance Methods // ----------------------------------------------------------------- @@ -322,20 +308,6 @@ private: Status SetupSoftwareSingleStepping(NativeThreadDarwin &thread); -#if 0 - static ::ProcessMessage::CrashReason - GetCrashReasonForSIGSEGV(const siginfo_t *info); - - static ::ProcessMessage::CrashReason - GetCrashReasonForSIGILL(const siginfo_t *info); - - static ::ProcessMessage::CrashReason - GetCrashReasonForSIGFPE(const siginfo_t *info); - - static ::ProcessMessage::CrashReason - GetCrashReasonForSIGBUS(const siginfo_t *info); -#endif - bool HasThreadNoLock(lldb::tid_t thread_id); bool StopTrackingThread(lldb::tid_t thread_id); diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index bd8e5abe2255..e6557c2d58e0 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -375,6 +375,7 @@ void FreeBSDThread::Notify(const ProcessMessage &message) { LimboNotify(message); break; + case ProcessMessage::eCrashMessage: case ProcessMessage::eSignalMessage: SignalNotify(message); break; @@ -395,10 +396,6 @@ void FreeBSDThread::Notify(const ProcessMessage &message) { WatchNotify(message); break; - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; - case ProcessMessage::eExecMessage: ExecNotify(message); break; @@ -577,7 +574,14 @@ void FreeBSDThread::LimboNotify(const ProcessMessage &message) { void FreeBSDThread::SignalNotify(const ProcessMessage &message) { int signo = message.GetSignal(); - SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); + if (message.GetKind() == ProcessMessage::eCrashMessage) { + std::string stop_description = GetCrashReasonString( + message.GetCrashReason(), message.GetFaultAddress()); + SetStopInfo(StopInfo::CreateStopReasonWithSignal( + *this, signo, stop_description.c_str())); + } else { + SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); + } } void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { @@ -585,21 +589,6 @@ void FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) { SetStopInfo(StopInfo::CreateStopReasonWithSignal(*this, signo)); } -void FreeBSDThread::CrashNotify(const ProcessMessage &message) { - // FIXME: Update stop reason as per bugzilla 14598 - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD)); - if (log) - log->Printf("FreeBSDThread::%s () signo = %i, reason = '%s'", __FUNCTION__, - signo, message.PrintCrashReason()); - - SetStopInfo(lldb::StopInfoSP(new POSIXCrashStopInfo( - *this, signo, message.GetCrashReason(), message.GetFaultAddress()))); -} - unsigned FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) { unsigned reg = LLDB_INVALID_REGNUM; ArchSpec arch = HostInfo::GetArchitecture(); diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp index dfbd695899ff..9c75c26e379b 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -28,22 +28,6 @@ bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; } bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; } //===----------------------------------------------------------------------===// -// POSIXCrashStopInfo - -POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, - CrashReason reason, - lldb::addr_t fault_addr) - : POSIXStopInfo(thread, status) { - m_description = ::GetCrashReasonString(reason, fault_addr); -} - -POSIXCrashStopInfo::~POSIXCrashStopInfo() {} - -lldb::StopReason POSIXCrashStopInfo::GetStopReason() const { - return lldb::eStopReasonException; -} - -//===----------------------------------------------------------------------===// // POSIXNewThreadStopInfo POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {} diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h index e51fc08d74cc..96861852b38e 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -45,19 +45,6 @@ public: }; //===----------------------------------------------------------------------===// -/// @class POSIXCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class POSIXCrashStopInfo : public POSIXStopInfo { -public: - POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status, CrashReason reason, - lldb::addr_t fault_addr); - ~POSIXCrashStopInfo(); - - lldb::StopReason GetStopReason() const; -}; - -//===----------------------------------------------------------------------===// /// @class POSIXNewThreadStopInfo /// @brief Represents the stop state of process when a new thread is spawned. /// diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 3046150e3246..7a937db49be0 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -825,32 +825,6 @@ uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() { return m_thread_list.GetSize(false); } -#if 0 -bool -ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); - - bool has_updated = false; - // Update the process thread list with this new thread. - // FIXME: We should be using tid, not pid. - assert(m_monitor); - ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); - if (!thread_sp) { - thread_sp.reset(CreateNewFreeBSDThread(*this, GetID())); - has_updated = true; - } - - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); - new_thread_list.AddThread(thread_sp); - - return has_updated; // the list has been updated -} -#endif - ByteOrder ProcessFreeBSD::GetByteOrder() const { // FIXME: We should be able to extract this value directly. See comment in // ProcessFreeBSD(). diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index a4f5f02dde62..bd06fa25f0a0 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -843,7 +843,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) { const FileSpec &stderr_file_spec = args->m_stderr_file_spec; const FileSpec &working_dir = args->m_working_dir; - lldb_utility::PseudoTerminal terminal; + PseudoTerminal terminal; const size_t err_len = 1024; char err_str[err_len]; ::pid_t pid; @@ -1192,7 +1192,9 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, case SIGBUS: lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr); const auto reason = GetCrashReason(*info); - return ProcessMessage::Crash(tid, reason, signo, fault_addr); + if (reason != CrashReason::eInvalidCrashReason) { + return ProcessMessage::Crash(tid, reason, signo, fault_addr); + } // else; Use atleast si_signo info for other si_code } // Everything else is "normal" and does not require any special action on diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h index c0b9b2f4a2d3..4ff5121bac13 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h @@ -14,8 +14,8 @@ // C++ Includes // Other libraries and framework includes #include "RegisterInfoInterface.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/ArchSpec.h" //------------------------------------------------------------------------------ /// @class POSIXBreakpointProtocol diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 1cd8f1aafa6e..4608520dba40 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -58,6 +58,9 @@ RegisterContextPOSIXProcessMonitor_x86_64:: // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset; + + m_iovec.iov_base = &m_fpr.xsave; + m_iovec.iov_len = sizeof(m_fpr.xsave); } ProcessMonitor &RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor() { @@ -74,12 +77,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadGPR() { bool RegisterContextPOSIXProcessMonitor_x86_64::ReadFPR() { ProcessMonitor &monitor = GetMonitor(); if (GetFPRType() == eFXSAVE) - return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, - sizeof(m_fpr.xstate.fxsave)); + return monitor.ReadFPR(m_thread.GetID(), &m_fpr.fxsave, + sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + sizeof(m_fpr.xsave), NT_X86_XSTATE); return false; } @@ -91,12 +94,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteGPR() { bool RegisterContextPOSIXProcessMonitor_x86_64::WriteFPR() { ProcessMonitor &monitor = GetMonitor(); if (GetFPRType() == eFXSAVE) - return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, - sizeof(m_fpr.xstate.fxsave)); + return monitor.WriteFPR(m_thread.GetID(), &m_fpr.fxsave, + sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, - sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE); + sizeof(m_fpr.xsave), NT_X86_XSTATE); return false; } @@ -209,17 +212,14 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( if (byte_order != ByteOrder::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); + 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) - value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); + 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) - value.SetBytes( - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); + 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 (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order)) @@ -233,7 +233,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister( return false; } - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + // 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(PT_GETFPREGS,..)} // and stores them in 'm_fpr' (of type FPR structure). To extract values of @@ -276,15 +276,15 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( if (IsFPR(reg, GetFPRType())) { if (reg_info->encoding == eEncodingVector) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, + ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_st].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm) - ::memcpy(m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, + ::memcpy(m_fpr.fxsave.stmm[reg - m_reg_info.first_mm].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm) - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, + ::memcpy(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, value.GetBytes(), value.GetByteSize()); if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) { @@ -299,7 +299,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister( return false; } } else { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + // 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 @@ -353,7 +353,7 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadAllRegisterValues( ::memcpy(dst, &m_gpr_x86_64, GetGPRSize()); dst += GetGPRSize(); if (GetFPRType() == eFXSAVE) - ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); } if (GetFPRType() == eXSAVE) { @@ -385,9 +385,9 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues( if (WriteGPR()) { src += GetGPRSize(); if (GetFPRType() == eFXSAVE) - ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); if (GetFPRType() == eXSAVE) - ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); success = WriteFPR(); if (success) { diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h index 57e2d00e668f..8c654f97dcd9 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h @@ -12,6 +12,7 @@ #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" #include "RegisterContextPOSIX.h" +#include <sys/uio.h> class RegisterContextPOSIXProcessMonitor_x86_64 : public RegisterContextPOSIX_x86, @@ -75,6 +76,7 @@ private: ProcessMonitor &GetMonitor(); uint32_t m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure + struct iovec m_iovec; }; #endif diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt index 8330cac160e6..390dbd9ff8bf 100644 --- a/source/Plugins/Process/Linux/CMakeLists.txt +++ b/source/Plugins/Process/Linux/CMakeLists.txt @@ -7,9 +7,10 @@ add_lldb_library(lldbPluginProcessLinux PLUGIN NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp NativeRegisterContextLinux_arm64.cpp - NativeRegisterContextLinux_x86_64.cpp NativeRegisterContextLinux_mips64.cpp + NativeRegisterContextLinux_ppc64le.cpp NativeRegisterContextLinux_s390x.cpp + NativeRegisterContextLinux_x86_64.cpp NativeThreadLinux.cpp ProcessorTrace.cpp SingleStepCheck.cpp diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 170d3b100064..136af361af29 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -177,7 +177,7 @@ void PtraceDisplayBytes(int &req, void *data, size_t data_size) { break; } case PTRACE_SETREGSET: { - // Extract iov_base from data, which is a pointer to the struct IOVEC + // 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; @@ -305,10 +305,9 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd, assert(m_sigchld_handle && status.Success()); for (const auto &tid : tids) { - NativeThreadLinuxSP thread_sp = AddThread(tid); - assert(thread_sp && "AddThread() returned a nullptr thread"); - thread_sp->SetStoppedBySignal(SIGSTOP); - ThreadWasCreated(*thread_sp); + NativeThreadLinux &thread = AddThread(tid); + thread.SetStoppedBySignal(SIGSTOP); + ThreadWasCreated(thread); } // Let our process instance know the thread has stopped. @@ -413,46 +412,20 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, // Handle when the thread exits. if (exited) { - LLDB_LOG(log, "got exit signal({0}) , tid = {1} ({2} main thread)", signal, - pid, is_main_thread ? "is" : "is not"); + 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. - const bool thread_found = StopTrackingThread(pid); + StopTrackingThread(pid); if (is_main_thread) { - // We only set the exit status and notify the delegate if we haven't - // already set the process - // state to an exited state. We normally should have received a SIGTRAP | - // (PTRACE_EVENT_EXIT << 8) - // for the main thread. - const bool already_notified = (GetState() == StateType::eStateExited) || - (GetState() == StateType::eStateCrashed); - if (!already_notified) { - LLDB_LOG( - log, - "tid = {0} handling main thread exit ({1}), expected exit state " - "already set but state was {2} instead, setting exit state now", - pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found", - GetState()); - // The main thread exited. We're done monitoring. Report to delegate. - SetExitStatus(status, true); + // 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); - } else - LLDB_LOG(log, "tid = {0} main thread now exited (%s)", pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); - } else { - // Do we want to report to the delegate in this case? I think not. If - // this was an orderly thread exit, we would already have received the - // SIGTRAP | (PTRACE_EVENT_EXIT << 8) signal, and we would have done an - // all-stop then. - LLDB_LOG(log, "tid = {0} handling non-main thread exit (%s)", pid, - thread_found ? "stopped tracking thread metadata" - : "thread metadata not found"); + // Notify delegate that our process has exited. + SetState(StateType::eStateExited, true); } return; } @@ -478,11 +451,11 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code, info.si_pid); - auto thread_sp = AddThread(pid); + NativeThreadLinux &thread = AddThread(pid); // Resume the newly created thread. - ResumeThread(*thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*thread_sp); + ResumeThread(thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(thread); return; } @@ -549,12 +522,9 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited, void NativeProcessLinux::WaitForNewThread(::pid_t tid) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - NativeThreadLinuxSP new_thread_sp = GetThreadByID(tid); - - if (new_thread_sp) { + 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. + // (see MonitorSignal) before this one. We are done. return; } @@ -587,10 +557,10 @@ void NativeProcessLinux::WaitForNewThread(::pid_t tid) { } LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid); - new_thread_sp = AddThread(tid); + NativeThreadLinux &new_thread = AddThread(tid); - ResumeThread(*new_thread_sp, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - ThreadWasCreated(*new_thread_sp); + ResumeThread(new_thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); + ThreadWasCreated(new_thread); } void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, @@ -630,7 +600,6 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, } case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)): { - NativeThreadLinuxSP main_thread_sp; LLDB_LOG(log, "received exec event, code = {0}", info.si_code ^ SIGTRAP); // Exec clears any pending notifications. @@ -640,44 +609,26 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, // which only copies the main thread. LLDB_LOG(log, "exec received, stop tracking all but main thread"); - for (auto thread_sp : m_threads) { - const bool is_main_thread = thread_sp && thread_sp->GetID() == GetID(); - if (is_main_thread) { - main_thread_sp = std::static_pointer_cast<NativeThreadLinux>(thread_sp); - LLDB_LOG(log, "found main thread with tid {0}, keeping", - main_thread_sp->GetID()); - } else { - LLDB_LOG(log, "discarding non-main-thread tid {0} due to exec", - thread_sp->GetID()); - } + 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()); - m_threads.clear(); - - if (main_thread_sp) { - m_threads.push_back(main_thread_sp); - SetCurrentThreadID(main_thread_sp->GetID()); - main_thread_sp->SetStoppedByExec(); - } else { - SetCurrentThreadID(LLDB_INVALID_THREAD_ID); - LLDB_LOG(log, - "pid {0} no main thread found, discarded all threads, " - "we're in a no-thread state!", - GetID()); - } + SetCurrentThreadID(main_thread->GetID()); + main_thread->SetStoppedByExec(); // Tell coordinator about about the "new" (since exec) stopped main thread. - ThreadWasCreated(*main_thread_sp); + ThreadWasCreated(*main_thread); // Let our delegate know we have just exec'd. NotifyDidExec(); - // If we have a main thread, indicate we are stopped. - assert(main_thread_sp && "exec called during ptraced process but no main " - "thread metadata tracked"); - // Let the process know we're stopped. - StopRunningThreads(main_thread_sp->GetID()); + StopRunningThreads(main_thread->GetID()); break; } @@ -685,10 +636,8 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, 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. + // 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()) @@ -700,18 +649,14 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, data, WIFEXITED(data), WIFSIGNALED(data), thread.GetID(), is_main_thread); - if (is_main_thread) - SetExitStatus(WaitStatus::Decode(data), true); 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. + // 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); @@ -725,7 +670,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( + Status error = thread.GetRegisterContext().GetWatchpointHitIndex( wp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, @@ -739,7 +684,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, // If a breakpoint was hit, report it uint32_t bp_index; - error = thread.GetRegisterContext()->GetHardwareBreakHitIndex( + error = thread.GetRegisterContext().GetHardwareBreakHitIndex( bp_index, (uintptr_t)info.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for hardware " @@ -762,7 +707,7 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = thread.GetRegisterContext()->GetWatchpointHitIndex( + Status error = thread.GetRegisterContext().GetWatchpointHitIndex( wp_index, LLDB_INVALID_ADDRESS); if (error.Fail()) LLDB_LOG(log, @@ -933,13 +878,13 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info, namespace { struct EmulatorBaton { - NativeProcessLinux *m_process; - NativeRegisterContext *m_reg_context; + NativeProcessLinux &m_process; + NativeRegisterContext &m_reg_context; // eRegisterKindDWARF -> RegsiterValue std::unordered_map<uint32_t, RegisterValue> m_register_values; - EmulatorBaton(NativeProcessLinux *process, NativeRegisterContext *reg_context) + EmulatorBaton(NativeProcessLinux &process, NativeRegisterContext ®_context) : m_process(process), m_reg_context(reg_context) {} }; @@ -951,7 +896,7 @@ static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton, EmulatorBaton *emulator_baton = static_cast<EmulatorBaton *>(baton); size_t bytes_read; - emulator_baton->m_process->ReadMemory(addr, dst, length, bytes_read); + emulator_baton->m_process.ReadMemory(addr, dst, length, bytes_read); return bytes_read; } @@ -971,11 +916,11 @@ static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton, // 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( + emulator_baton->m_reg_context.GetRegisterInfo( eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]); Status error = - emulator_baton->m_reg_context->ReadRegister(full_reg_info, reg_value); + emulator_baton->m_reg_context.ReadRegister(full_reg_info, reg_value); if (error.Success()) return true; @@ -999,17 +944,17 @@ static size_t WriteMemoryCallback(EmulateInstruction *instruction, void *baton, return length; } -static lldb::addr_t ReadFlags(NativeRegisterContext *regsiter_context) { - const RegisterInfo *flags_info = regsiter_context->GetRegisterInfo( +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); + return regsiter_context.ReadRegisterAsUnsigned(flags_info, + LLDB_INVALID_ADDRESS); } Status NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { Status error; - NativeRegisterContextSP register_context_sp = thread.GetRegisterContext(); + NativeRegisterContext& register_context = thread.GetRegisterContext(); std::unique_ptr<EmulateInstruction> emulator_ap( EmulateInstruction::FindPlugin(m_arch, eInstructionTypePCModifying, @@ -1018,7 +963,7 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { if (emulator_ap == nullptr) return Status("Instruction emulator not found!"); - EmulatorBaton baton(this, register_context_sp.get()); + EmulatorBaton baton(*this, register_context); emulator_ap->SetBaton(&baton); emulator_ap->SetReadMemCallback(&ReadMemoryCallback); emulator_ap->SetReadRegCallback(&ReadRegisterCallback); @@ -1031,9 +976,9 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { bool emulation_result = emulator_ap->EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); - const RegisterInfo *reg_info_pc = register_context_sp->GetRegisterInfo( + const RegisterInfo *reg_info_pc = register_context.GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - const RegisterInfo *reg_info_flags = register_context_sp->GetRegisterInfo( + const RegisterInfo *reg_info_flags = register_context.GetRegisterInfo( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); auto pc_it = @@ -1051,15 +996,14 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { if (flags_it != baton.m_register_values.end()) next_flags = flags_it->second.GetAsUInt64(); else - next_flags = ReadFlags(register_context_sp.get()); + 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_sp->GetPC() + emulator_ap->GetOpcode().GetByteSize(); - next_flags = ReadFlags(register_context_sp.get()); + 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 @@ -1078,7 +1022,8 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) { } 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::mipsel || + m_arch.GetMachine() == llvm::Triple::ppc64le) error = SetSoftwareBreakpoint(next_pc, 4); else { // No size hint is given for the next breakpoint @@ -1114,44 +1059,44 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { bool software_single_step = !SupportHardwareSingleStepping(); if (software_single_step) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) continue; if (action->state == eStateStepping) { Status error = SetupSoftwareSingleStepping( - static_cast<NativeThreadLinux &>(*thread_sp)); + static_cast<NativeThreadLinux &>(*thread)); if (error.Fail()) return error; } } } - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); + for (const auto &thread : m_threads) { + assert(thread && "thread list should not contain NULL threads"); const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread_sp->GetID()); + thread->GetID()); continue; } LLDB_LOG(log, "processing resume action state {0} for pid {1} tid {2}", - action->state, GetID(), thread_sp->GetID()); + 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_sp), action->state, + ResumeThread(static_cast<NativeThreadLinux &>(*thread), action->state, signo); break; } @@ -1164,7 +1109,7 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) { return Status("NativeProcessLinux::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), - thread_sp->GetID()); + thread->GetID()); } } @@ -1190,8 +1135,8 @@ Status NativeProcessLinux::Detach() { if (GetID() == LLDB_INVALID_PROCESS_ID) return error; - for (auto thread_sp : m_threads) { - Status e = Detach(thread_sp->GetID()); + 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. @@ -1221,29 +1166,25 @@ Status NativeProcessLinux::Interrupt() { // the chosen thread that will be the stop-reason thread. Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - NativeThreadProtocolSP running_thread_sp; - NativeThreadProtocolSP stopped_thread_sp; + NativeThreadProtocol *running_thread = nullptr; + NativeThreadProtocol *stopped_thread = nullptr; LLDB_LOG(log, "selecting running thread for interrupt target"); - for (auto thread_sp : m_threads) { - // The thread shouldn't be null but lets just cover that here. - if (!thread_sp) - continue; - + 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_sp->GetState(); + const auto thread_state = thread->GetState(); if (thread_state == eStateRunning || thread_state == eStateStepping) { - running_thread_sp = thread_sp; + running_thread = thread.get(); break; - } else if (!stopped_thread_sp && StateIsStoppedState(thread_state, true)) { + } 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_sp = thread_sp; + stopped_thread = thread.get(); } } - if (!running_thread_sp && !stopped_thread_sp) { + 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); @@ -1251,14 +1192,14 @@ Status NativeProcessLinux::Interrupt() { return error; } - NativeThreadProtocolSP deferred_signal_thread_sp = - running_thread_sp ? running_thread_sp : stopped_thread_sp; + 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_sp ? "running" : "stopped", - deferred_signal_thread_sp->GetID()); + running_thread ? "running" : "stopped", + deferred_signal_thread->GetID()); - StopRunningThreads(deferred_signal_thread_sp->GetID()); + StopRunningThreads(deferred_signal_thread->GetID()); return Status(); } @@ -1568,17 +1509,13 @@ size_t NativeProcessLinux::UpdateThreads() { return m_threads.size(); } -bool NativeProcessLinux::GetArchitecture(ArchSpec &arch) const { - arch = m_arch; - return true; -} - Status NativeProcessLinux::GetSoftwareBreakpointPCOffset( uint32_t &actual_opcode_size) { // FIXME put this behind a breakpoint protocol class that can be // set per architecture. Need ARM, MIPS support here. static const uint8_t g_i386_opcode[] = {0xCC}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap switch (m_arch.GetMachine()) { case llvm::Triple::x86: @@ -1590,6 +1527,10 @@ Status NativeProcessLinux::GetSoftwareBreakpointPCOffset( actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode)); return Status(); + case llvm::Triple::ppc64le: + actual_opcode_size = static_cast<uint32_t>(sizeof(g_ppc64le_opcode)); + return Status(); + case llvm::Triple::arm: case llvm::Triple::aarch64: case llvm::Triple::mips64: @@ -1635,6 +1576,7 @@ Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde}; + static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap switch (m_arch.GetMachine()) { case llvm::Triple::aarch64: @@ -1680,6 +1622,11 @@ Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode( actual_opcode_size = sizeof(g_s390x_opcode); return Status(); + case llvm::Triple::ppc64le: + trap_opcode_bytes = g_ppc64le_opcode; + actual_opcode_size = sizeof(g_ppc64le_opcode); + return Status(); + default: assert(false && "CPU type not supported!"); return Status("CPU type not supported"); @@ -1963,9 +1910,9 @@ Status NativeProcessLinux::Detach(lldb::tid_t tid) { } bool NativeProcessLinux::HasThreadNoLock(lldb::tid_t thread_id) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); - if (thread_sp->GetID() == 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; } @@ -1994,7 +1941,7 @@ bool NativeProcessLinux::StopTrackingThread(lldb::tid_t thread_id) { return found; } -NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { +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); @@ -2005,8 +1952,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - auto thread_sp = std::make_shared<NativeThreadLinux>(*this, thread_id); - m_threads.push_back(thread_sp); + m_threads.push_back(llvm::make_unique<NativeThreadLinux>(*this, thread_id)); if (m_pt_proces_trace_id != LLDB_INVALID_UID) { auto traceMonitor = ProcessorTraceMonitor::Create( @@ -2022,7 +1968,7 @@ NativeThreadLinuxSP NativeProcessLinux::AddThread(lldb::tid_t thread_id) { } } - return thread_sp; + return static_cast<NativeThreadLinux &>(*m_threads.back()); } Status @@ -2033,12 +1979,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { // Find out the size of a breakpoint (might depend on where we are in the // code). - NativeRegisterContextSP context_sp = thread.GetRegisterContext(); - if (!context_sp) { - error.SetErrorString("cannot get a NativeRegisterContext for the thread"); - LLDB_LOG(log, "failed: {0}", error); - return error; - } + NativeRegisterContext &context = thread.GetRegisterContext(); uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); @@ -2050,8 +1991,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { // First try probing for a breakpoint at a software breakpoint location: PC - // breakpoint size. - const lldb::addr_t initial_pc_addr = - context_sp->GetPCfromBreakpointLocation(); + const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. @@ -2098,7 +2038,7 @@ NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) { LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); - error = context_sp->SetPC(breakpoint_addr); + error = context.SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); @@ -2144,8 +2084,8 @@ Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name, return Status("No load address found for specified file."); } -NativeThreadLinuxSP NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { - return std::static_pointer_cast<NativeThreadLinux>( +NativeThreadLinux *NativeProcessLinux::GetThreadByID(lldb::tid_t tid) { + return static_cast<NativeThreadLinux *>( NativeProcessProtocol::GetThreadByID(tid)); } @@ -2200,9 +2140,9 @@ void NativeProcessLinux::StopRunningThreads(const lldb::tid_t 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_sp : m_threads) { - if (StateIsRunningState(thread_sp->GetState())) - static_pointer_cast<NativeThreadLinux>(thread_sp)->RequestStop(); + for (const auto &thread : m_threads) { + if (StateIsRunningState(thread->GetState())) + static_cast<NativeThreadLinux *>(thread.get())->RequestStop(); } SignalIfAllThreadsStopped(); diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index c9ec002760f8..f078c1ac30e2 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -13,12 +13,11 @@ #include <csignal> #include <unordered_set> -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #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" @@ -87,7 +86,7 @@ public: size_t UpdateThreads() override; - bool GetArchitecture(ArchSpec &arch) const override; + const ArchSpec &GetArchitecture() const override { return m_arch; } Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; @@ -102,7 +101,7 @@ public: Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override; - NativeThreadLinuxSP GetThreadByID(lldb::tid_t id); + NativeThreadLinux *GetThreadByID(lldb::tid_t id); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> GetAuxvData() const override { @@ -203,7 +202,7 @@ private: bool StopTrackingThread(lldb::tid_t thread_id); - NativeThreadLinuxSP AddThread(lldb::tid_t thread_id); + NativeThreadLinux &AddThread(lldb::tid_t thread_id); Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size); diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp index 30f09f0c3a3f..c8a8355f9cb9 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -14,27 +14,19 @@ #include "lldb/Host/common/NativeThreadProtocol.h" #include "lldb/Host/linux/Ptrace.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, uint32_t concrete_frame_idx, + NativeThreadProtocol &native_thread, RegisterInfoInterface *reg_info_interface_p) - : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, - reg_info_interface_p) {} + : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {} lldb::ByteOrder NativeRegisterContextLinux::GetByteOrder() const { - // Get the target process whose privileged thread was used for the register - // read. - lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; - - if (!m_thread.GetProcess().GetByteOrder(byte_order)) { - // FIXME log here - } - - return byte_order; + return m_thread.GetProcess().GetByteOrder(); } Status NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h index 26074a6ce0e3..2cea497b53bc 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -10,10 +10,8 @@ #ifndef lldb_NativeRegisterContextLinux_h #define lldb_NativeRegisterContextLinux_h -#include "lldb/Host/common/NativeThreadProtocol.h" - -#include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" +#include "lldb/Host/common/NativeThreadProtocol.h" namespace lldb_private { namespace process_linux { @@ -21,20 +19,15 @@ namespace process_linux { class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo { public: NativeRegisterContextLinux(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, 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 NativeRegisterContextLinux * + // 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, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); protected: lldb::ByteOrder GetByteOrder() const; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 22b7d10869fe..cb05416cb6c3 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -11,15 +11,15 @@ #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/Core/RegisterValue.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Status.h" -#include "Plugins/Process/Linux/Procfs.h" -#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" - #include <elf.h> #include <sys/socket.h> @@ -95,20 +95,18 @@ static const RegisterSet g_reg_sets_arm[k_num_register_sets] = { #if defined(__arm__) -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_arm(target_arch, native_thread, - concrete_frame_idx); + 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, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, new RegisterInfoPOSIX_arm(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index ec99c05e1644..40e3b80eda74 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -23,8 +23,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_arm(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 7aad062e3f93..c483260a5b2c 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -112,26 +112,24 @@ static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = { {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64}}; -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { switch (target_arch.GetMachine()) { case llvm::Triple::arm: - return new NativeRegisterContextLinux_arm(target_arch, native_thread, - concrete_frame_idx); + return llvm::make_unique<NativeRegisterContextLinux_arm>(target_arch, + native_thread); case llvm::Triple::aarch64: - return new NativeRegisterContextLinux_arm64(target_arch, native_thread, - concrete_frame_idx); + 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, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: @@ -872,12 +870,8 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { - ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, - arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); + value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, + m_thread.GetProcess().GetByteOrder()); } } else { elf_gregset_t regs; @@ -889,12 +883,8 @@ Status NativeRegisterContextLinux_arm64::DoReadRegisterValue( error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGSET, m_thread.GetID(), ®set, &ioVec, sizeof regs); if (error.Success()) { - ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) - value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, - arch.GetByteOrder()); - else - error.SetErrorString("failed to get architecture"); + value.SetBytes((void *)(((unsigned char *)(regs)) + offset), 8, + m_thread.GetProcess().GetByteOrder()); } } return error; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 9877dec37c48..ab3c881ead59 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -23,8 +23,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index f35ff2be0d94..32c04a4374e6 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -80,12 +80,11 @@ struct pt_watch_regs default_watch_regs; using namespace lldb_private; using namespace lldb_private::process_linux; -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_mips64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return llvm::make_unique<NativeRegisterContextLinux_mips64>(target_arch, + native_thread); } #define REG_CONTEXT_SIZE \ @@ -110,9 +109,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextLinux(native_thread, CreateRegisterInfoInterface(target_arch)) { switch (target_arch.GetMachine()) { case llvm::Triple::mips: @@ -1033,13 +1031,11 @@ Status NativeRegisterContextLinux_mips64::Read_SR_Config(uint32_t offset, Status error = NativeProcessLinux::PtraceWrapper( PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); if (error.Success()) { - lldb_private::ArchSpec arch; - if (m_thread.GetProcess().GetArchitecture(arch)) { - void *target_address = ((uint8_t *)®s) + offset + - 4 * (arch.GetMachine() == llvm::Triple::mips); - value.SetUInt(*(uint32_t *)target_address, size); - } else - error.SetErrorString("failed to get architecture"); + 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; } diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h index 3e14da5a2725..c4e984a545bc 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -15,6 +15,7 @@ #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 @@ -26,8 +27,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_mips64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; @@ -129,7 +129,7 @@ private: lldb::addr_t hw_addr_map[MAX_NUM_WP]; - IOVEC_mips m_iovec; + struct iovec m_iovec; }; } // namespace process_linux diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp new file mode 100644 index 000000000000..ea854dfa1dc6 --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp @@ -0,0 +1,801 @@ +//===-- 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/Core/RegisterValue.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.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, +}; + +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, +}; + +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, +}; + +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, +}; + +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 new file mode 100644 index 000000000000..bb25af80d02c --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h @@ -0,0 +1,149 @@ +//===-- 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 "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 mangement 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 index c2a696e08bf9..021394ab154b 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -97,12 +97,11 @@ static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { #define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_s390x(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return llvm::make_unique<NativeRegisterContextLinux_s390x>(target_arch, + native_thread); } // ---------------------------------------------------------------------------- @@ -117,9 +116,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + 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()) { diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h index 3ffbaeeb0bba..57b1a0481512 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h @@ -24,8 +24,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp index e44e03b46b5c..84ffe9b6e420 100755 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -243,12 +243,11 @@ static inline unsigned int fxsr_regset(const ArchSpec &arch) { #define mask_XSTATE_BNDCFG (1ULL << 4) #define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG) -NativeRegisterContextLinux * +std::unique_ptr<NativeRegisterContextLinux> NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return std::unique_ptr<NativeRegisterContextLinux>( + new NativeRegisterContextLinux_x86_64(target_arch, native_thread)); } // ---------------------------------------------------------------------------- @@ -270,9 +269,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + 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() { @@ -334,11 +332,11 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64( // 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.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); + m_iovec.iov_base = &m_fpr; + m_iovec.iov_len = sizeof(m_fpr); // Clear out the FPR state. - ::memset(&m_fpr, 0, sizeof(FPR)); + ::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"); @@ -441,17 +439,14 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, if (byte_order != lldb::eByteOrderInvalid) { if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st) - reg_value.SetBytes( - m_fpr.xstate.fxsave.stmm[reg - m_reg_info.first_st].bytes, - reg_info->byte_size, byte_order); + 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.xstate.fxsave.stmm[reg - m_reg_info.first_mm].bytes, - reg_info->byte_size, byte_order); + 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.xstate.fxsave.xmm[reg - m_reg_info.first_xmm].bytes, - reg_info->byte_size, byte_order); + 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)) @@ -492,7 +487,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, return error; } - // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. + // 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,..)} @@ -530,6 +525,22 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, 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"); @@ -540,25 +551,24 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( ? 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.xstate.fxsave.stmm[reg_index - m_reg_info.first_st].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::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.xstate.fxsave.stmm[reg_index - m_reg_info.first_mm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::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.xstate.fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes, - reg_value.GetBytes(), reg_value.GetByteSize()); + ::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) { @@ -586,7 +596,7 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister( return Status("CopyMPXtoXSTATE() failed"); } } else { - // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. + // 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 @@ -658,7 +668,7 @@ Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues( ::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize()); dst += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(dst, &m_fpr.fxsave, sizeof(m_fpr.fxsave)); else if (m_xstate_type == XStateType::XSAVE) { lldb::ByteOrder byte_order = GetByteOrder(); @@ -749,9 +759,9 @@ Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues( src += GetRegisterInfoInterface().GetGPRSize(); if (m_xstate_type == XStateType::FXSAVE) - ::memcpy(&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave)); + ::memcpy(&m_fpr.fxsave, src, sizeof(m_fpr.fxsave)); else if (m_xstate_type == XStateType::XSAVE) - ::memcpy(&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave)); + ::memcpy(&m_fpr.xsave, src, sizeof(m_fpr.xsave)); error = WriteFPR(); if (error.Fail()) @@ -805,12 +815,12 @@ bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable( 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.xstate.xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX) + 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.xstate.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) + if ((m_fpr.xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX) return true; break; } @@ -847,11 +857,10 @@ Status NativeRegisterContextLinux_x86_64::WriteFPR() { switch (m_xstate_type) { case XStateType::FXSAVE: return WriteRegisterSet( - &m_iovec, sizeof(m_fpr.xstate.xsave), + &m_iovec, sizeof(m_fpr.fxsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); case XStateType::XSAVE: - return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), - NT_X86_XSTATE); + return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xsave), NT_X86_XSTATE); default: return Status("Unrecognized FPR type."); } @@ -871,11 +880,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[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.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -883,10 +892,10 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM( if (byte_order == lldb::eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.fxsave.xmm[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, - m_fpr.xstate.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg_index - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } @@ -899,19 +908,19 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( return false; if (byte_order == lldb::eByteOrderLittle) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::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.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::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.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::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.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::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; } @@ -921,7 +930,7 @@ bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE( void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { switch (m_xstate_type) { case XStateType::FXSAVE: - return &m_fpr.xstate.fxsave; + return &m_fpr.fxsave; case XStateType::XSAVE: return &m_iovec; default: @@ -932,7 +941,7 @@ void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() { size_t NativeRegisterContextLinux_x86_64::GetFPRSize() { switch (m_xstate_type) { case XStateType::FXSAVE: - return sizeof(m_fpr.xstate.fxsave); + return sizeof(m_fpr.fxsave); case XStateType::XSAVE: return sizeof(m_iovec); default: @@ -945,15 +954,14 @@ Status NativeRegisterContextLinux_x86_64::ReadFPR() { // 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.xstate.xsave), NT_X86_XSTATE); + 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.xstate.xsave), + &m_iovec, sizeof(m_fpr.xsave), fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture())); if (!error.Fail()) { m_xstate_type = XStateType::FXSAVE; @@ -975,11 +983,11 @@ bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) { 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.xstate.xsave.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.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + m_fpr.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr)); } return true; @@ -990,10 +998,10 @@ bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) { return false; if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) { - ::memcpy(m_fpr.xstate.xsave.mpxr[reg - m_reg_info.first_mpxr].bytes, + ::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.xstate.xsave.mpxc[reg - m_reg_info.first_mpxc].bytes, + ::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; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h index abb0dba4d91c..9dcf82f50a45 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.h @@ -15,6 +15,7 @@ #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 { @@ -24,8 +25,7 @@ class NativeProcessLinux; class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_x86_64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; @@ -110,7 +110,7 @@ private: // Private member variables. mutable XStateType m_xstate_type; FPR m_fpr; // Extended States Area, named FPR for historical reasons. - IOVEC m_iovec; + struct iovec m_iovec; YMM m_ymm_set; MPX m_mpx_set; RegInfo m_reg_info; @@ -137,6 +137,8 @@ private: bool CopyMPXtoXSTATE(uint32_t reg); bool IsMPX(uint32_t reg_index) const; + + void UpdateXSTATEforWrite(uint32_t reg_index); }; } // namespace process_linux diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp index 5cd40941dcf8..0db3bd56b8e4 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -88,7 +88,11 @@ void LogThreadStopInfo(Log &log, const ThreadStopInfo &stop_info, NativeThreadLinux::NativeThreadLinux(NativeProcessLinux &process, lldb::tid_t tid) : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), - m_stop_info(), m_reg_context_sp(), m_stop_description() {} + m_stop_info(), + m_reg_context_up( + NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + process.GetArchitecture(), *this)), + m_stop_description() {} std::string NativeThreadLinux::GetName() { NativeProcessLinux &process = GetProcess(); @@ -139,23 +143,6 @@ bool NativeThreadLinux::GetStopReason(ThreadStopInfo &stop_info, llvm_unreachable("unhandled StateType!"); } -NativeRegisterContextSP NativeThreadLinux::GetRegisterContext() { - // Return the register context if we already created it. - if (m_reg_context_sp) - return m_reg_context_sp; - - ArchSpec target_arch; - if (!m_process.GetArchitecture(target_arch)) - return NativeRegisterContextSP(); - - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset( - NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( - target_arch, *this, concrete_frame_idx)); - - return m_reg_context_sp; -} - Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) { if (!hardware) @@ -165,8 +152,8 @@ Status NativeThreadLinux::SetWatchpoint(lldb::addr_t addr, size_t size, Status error = RemoveWatchpoint(addr); if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + 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}); @@ -179,7 +166,7 @@ Status NativeThreadLinux::RemoveWatchpoint(lldb::addr_t addr) { return Status(); uint32_t wp_index = wp->second; m_watchpoint_index_map.erase(wp); - if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + if (m_reg_context_up->ClearHardwareWatchpoint(wp_index)) return Status(); return Status("Clearing hardware watchpoint failed."); } @@ -193,8 +180,7 @@ Status NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + uint32_t bp_index = m_reg_context_up->SetHardwareBreakpoint(addr, size); if (bp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware breakpoint failed."); @@ -209,7 +195,7 @@ Status NativeThreadLinux::RemoveHardwareBreakpoint(lldb::addr_t addr) { return Status(); uint32_t bp_index = bp->second; - if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + if (m_reg_context_up->ClearHardwareBreakpoint(bp_index)) { m_hw_break_index_map.erase(bp); return Status(); } @@ -231,7 +217,7 @@ Status NativeThreadLinux::Resume(uint32_t signo) { NativeProcessLinux &process = GetProcess(); const auto &watchpoint_map = process.GetWatchpointMap(); - GetRegisterContext()->ClearAllHardwareWatchpoints(); + 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); @@ -243,7 +229,7 @@ Status NativeThreadLinux::Resume(uint32_t signo) { NativeProcessLinux &process = GetProcess(); const auto &hw_breakpoint_map = process.GetHardwareBreakpointMap(); - GetRegisterContext()->ClearAllHardwareBreakpoints(); + m_reg_context_up->ClearAllHardwareBreakpoints(); for (const auto &pair : hw_breakpoint_map) { const auto &bp = pair.second; SetHardwareBreakpoint(bp.m_addr, bp.m_size); @@ -365,7 +351,7 @@ void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); std::ostringstream ostr; - ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << m_reg_context_up->GetWatchpointAddress(wp_index) << " "; ostr << wp_index; /* @@ -379,7 +365,7 @@ void NativeThreadLinux::SetStoppedByWatchpoint(uint32_t wp_index) { * stop-info * packet. */ - ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + ostr << " " << m_reg_context_up->GetWatchpointHitAddress(wp_index); m_stop_description = ostr.str(); diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h index 6ae87feffcda..a7c4e982012d 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -10,7 +10,8 @@ #ifndef liblldb_NativeThreadLinux_H_ #define liblldb_NativeThreadLinux_H_ -#include "SingleStepCheck.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" @@ -40,7 +41,9 @@ public: bool GetStopReason(ThreadStopInfo &stop_info, std::string &description) override; - NativeRegisterContextSP GetRegisterContext() 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; @@ -103,15 +106,13 @@ private: // --------------------------------------------------------------------- lldb::StateType m_state; ThreadStopInfo m_stop_info; - NativeRegisterContextSP m_reg_context_sp; + 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; }; - -typedef std::shared_ptr<NativeThreadLinux> NativeThreadLinuxSP; } // namespace process_linux } // namespace lldb_private diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 52b9441e0e79..b4eae58af83c 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -17,12 +17,12 @@ #include <vector> // Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Broadcaster.h" #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/ConstString.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/StreamString.h" diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp index ae2f11f38006..1902cc492ff4 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp @@ -12,13 +12,13 @@ #include "lldb/Utility/SafeMachO.h" #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/State.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/StreamString.h" diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 388989a21f76..387f04afa5b4 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -109,10 +109,8 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info, if (status.Fail()) return status.ToError(); - for (const auto &thread_sp : process_up->m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } + for (const auto &thread : process_up->m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP); process_up->SetState(StateType::eStateStopped); return std::move(process_up); @@ -198,9 +196,9 @@ void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) { // Handle SIGSTOP from LLGS (LLDB GDB Server) if (info.psi_siginfo.si_code == SI_USER && info.psi_siginfo.si_pid == ::getpid()) { - /* Stop Tracking All Threads attached to Process */ - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + /* Stop Tracking all Threads attached to Process */ + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal( SIGSTOP, &info.psi_siginfo); } } @@ -221,18 +219,15 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { switch (info.psi_siginfo.si_code) { case TRAP_BRKPT: - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByBreakpoint(); - FixupBreakpointPCAsNeeded( - *static_pointer_cast<NativeThreadNetBSD>(thread_sp)); + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint(); + FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread)); } SetState(StateType::eStateStopped, true); break; case TRAP_TRACE: - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByTrace(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace(); SetState(StateType::eStateStopped, true); break; case TRAP_EXEC: { @@ -245,38 +240,35 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { // Let our delegate know we have just exec'd. NotifyDidExec(); - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedByExec(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec(); SetState(StateType::eStateStopped, true); } break; case TRAP_DBREG: { // If a watchpoint was hit, report it uint32_t wp_index; - Status error = - static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) - ->GetRegisterContext() - ->GetWatchpointHitIndex(wp_index, - (uintptr_t)info.psi_siginfo.si_addr); + Status error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid]) + .GetRegisterContext() + .GetWatchpointHitIndex( + wp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, "received error while checking for watchpoint hits, pid = " "{0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (wp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByWatchpoint(wp_index); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint( + wp_index); SetState(StateType::eStateStopped, true); break; } // If a breakpoint was hit, report it uint32_t bp_index; - error = static_pointer_cast<NativeThreadNetBSD>(m_threads[info.psi_lwpid]) - ->GetRegisterContext() - ->GetHardwareBreakHitIndex(bp_index, + error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid]) + .GetRegisterContext() + .GetHardwareBreakHitIndex(bp_index, (uintptr_t)info.psi_siginfo.si_addr); if (error.Fail()) LLDB_LOG(log, @@ -284,10 +276,8 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { "breakpoint hits, pid = {0}, LWP = {1}, error = {2}", GetID(), info.psi_lwpid, error); if (bp_index != LLDB_INVALID_INDEX32) { - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp) - ->SetStoppedByBreakpoint(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint(); SetState(StateType::eStateStopped, true); break; } @@ -300,8 +290,8 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) { const auto siginfo_err = PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info)); - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( + for (const auto &thread : m_threads) { + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal( info.psi_siginfo.si_signo, &info.psi_siginfo); } SetState(StateType::eStateStopped, true); @@ -351,12 +341,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { Status error; // Find out the size of a breakpoint (might depend on where we are in the // code). - NativeRegisterContextSP context_sp = thread.GetRegisterContext(); - if (!context_sp) { - error.SetErrorString("cannot get a NativeRegisterContext for the thread"); - LLDB_LOG(log, "failed: {0}", error); - return error; - } + NativeRegisterContext& context = thread.GetRegisterContext(); uint32_t breakpoint_size = 0; error = GetSoftwareBreakpointPCOffset(breakpoint_size); if (error.Fail()) { @@ -367,7 +352,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { // First try probing for a breakpoint at a software breakpoint location: PC // - breakpoint size. const lldb::addr_t initial_pc_addr = - context_sp->GetPCfromBreakpointLocation(); + context.GetPCfromBreakpointLocation(); lldb::addr_t breakpoint_addr = initial_pc_addr; if (breakpoint_size > 0) { // Do not allow breakpoint probe to wrap around. @@ -420,7 +405,7 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) { // Change the program counter. LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(), thread.GetID(), initial_pc_addr, breakpoint_addr); - error = context_sp->SetPC(breakpoint_addr); + error = context.SetPC(breakpoint_addr); if (error.Fail()) { LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(), thread.GetID(), error); @@ -433,13 +418,13 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); LLDB_LOG(log, "pid {0}", GetID()); - const auto &thread_sp = m_threads[0]; + const auto &thread = m_threads[0]; const ResumeAction *const action = - resume_actions.GetActionForThread(thread_sp->GetID(), true); + resume_actions.GetActionForThread(thread->GetID(), true); if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), - thread_sp->GetID()); + thread->GetID()); return Status(); } @@ -452,9 +437,8 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { action->signal); if (!error.Success()) return error; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetRunning(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetRunning(); SetState(eStateRunning, true); break; } @@ -464,9 +448,8 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { action->signal); if (!error.Success()) return error; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStepping(); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStepping(); SetState(eStateStepping, true); break; @@ -478,7 +461,7 @@ Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) { return Status("NativeProcessNetBSD::%s (): unexpected state %s specified " "for pid %" PRIu64 ", tid %" PRIu64, __FUNCTION__, StateAsCString(action->state), GetID(), - thread_sp->GetID()); + thread->GetID()); } return Status(); @@ -690,11 +673,6 @@ lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() { size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); } -bool NativeProcessNetBSD::GetArchitecture(ArchSpec &arch) const { - arch = m_arch; - return true; -} - Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) { if (hardware) @@ -764,9 +742,9 @@ void NativeProcessNetBSD::SigchldHandler() { } bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { - for (auto thread_sp : m_threads) { - assert(thread_sp && "thread list should not contain NULL threads"); - if (thread_sp->GetID() == 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; } @@ -776,7 +754,7 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) { return false; } -NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { +NativeThreadNetBSD &NativeProcessNetBSD::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); @@ -788,9 +766,8 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) { if (m_threads.empty()) SetCurrentThreadID(thread_id); - auto thread_sp = std::make_shared<NativeThreadNetBSD>(*this, thread_id); - m_threads.push_back(thread_sp); - return thread_sp; + m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id)); + return static_cast<NativeThreadNetBSD &>(*m_threads.back()); } Status NativeProcessNetBSD::Attach() { @@ -811,10 +788,8 @@ Status NativeProcessNetBSD::Attach() { if (status.Fail()) return status; - for (const auto &thread_sp : m_threads) { - static_pointer_cast<NativeThreadNetBSD>(thread_sp)->SetStoppedBySignal( - SIGSTOP); - } + for (const auto &thread : m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP); // Let our process instance know the thread has stopped. SetState(StateType::eStateStopped); @@ -928,7 +903,7 @@ Status NativeProcessNetBSD::ReinitializeThreads() { } // Reinitialize from scratch threads and register them in process while (info.pl_lwpid != 0) { - NativeThreadNetBSDSP thread_sp = AddThread(info.pl_lwpid); + AddThread(info.pl_lwpid); error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info)); if (error.Fail()) { return error; diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 2cbd5e30ab23..7090fce34fc9 100644 --- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -10,12 +10,8 @@ #ifndef liblldb_NativeProcessNetBSD_H_ #define liblldb_NativeProcessNetBSD_H_ -// C++ Includes - -// Other libraries and framework includes - -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/FileSpec.h" #include "NativeThreadNetBSD.h" @@ -77,7 +73,7 @@ public: size_t UpdateThreads() override; - bool GetArchitecture(ArchSpec &arch) const override; + const ArchSpec &GetArchitecture() const override { return m_arch; } Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override; @@ -121,7 +117,7 @@ private: bool HasThreadNoLock(lldb::tid_t thread_id); - NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id); + NativeThreadNetBSD &AddThread(lldb::tid_t thread_id); void MonitorCallback(lldb::pid_t pid, int signal); void MonitorExited(lldb::pid_t pid, WaitStatus status); diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp index dde86880c41a..d4fef6342439 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp @@ -20,9 +20,9 @@ using namespace lldb_private::process_netbsd; // clang-format on NativeRegisterContextNetBSD::NativeRegisterContextNetBSD( - NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &native_thread, RegisterInfoInterface *reg_info_interface_p) - : NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, + : NativeRegisterContextRegisterInfo(native_thread, reg_info_interface_p) {} Status NativeRegisterContextNetBSD::ReadGPR() { diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h index d96b7aea0048..b81430e7f5ac 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h @@ -21,7 +21,6 @@ namespace process_netbsd { class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo { public: NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p); // This function is implemented in the NativeRegisterContextNetBSD_* @@ -31,8 +30,7 @@ public: // executable. static NativeRegisterContextNetBSD * CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); protected: virtual Status ReadGPR(); diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index 9690da0e1374..347c15ae5b23 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -149,10 +149,8 @@ const int fpu_save = []() -> int { NativeRegisterContextNetBSD * NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) { - return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread, - concrete_frame_idx); + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { + return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread); } // ---------------------------------------------------------------------------- @@ -169,9 +167,8 @@ CreateRegisterInfoInterface(const ArchSpec &target_arch) { } NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextNetBSD(native_thread, concrete_frame_idx, + const ArchSpec &target_arch, NativeThreadProtocol &native_thread) + : NativeRegisterContextNetBSD(native_thread, CreateRegisterInfoInterface(target_arch)), m_gpr_x86_64(), m_fpr_x86_64(), m_dbr_x86_64() {} diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h index 5f5a6a0792e4..c55ddfec6615 100644 --- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h +++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h @@ -30,8 +30,7 @@ class NativeProcessNetBSD; class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD { public: NativeRegisterContextNetBSD_x86_64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx); + NativeThreadProtocol &native_thread); uint32_t GetRegisterSetCount() const override; const RegisterSet *GetRegisterSet(uint32_t set_index) const override; diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index 1fd7400bf800..83f1da78d01d 100644 --- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -27,7 +27,9 @@ using namespace lldb_private::process_netbsd; NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process, lldb::tid_t tid) : NativeThreadProtocol(process, tid), m_state(StateType::eStateInvalid), - m_stop_info(), m_reg_context_sp(), m_stop_description() {} + m_stop_info(), m_reg_context_up( +NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this) +), m_stop_description() {} void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) { @@ -77,10 +79,10 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); std::ostringstream ostr; - ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " "; + ostr << GetRegisterContext().GetWatchpointAddress(wp_index) << " "; ostr << wp_index; - ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index); + ostr << " " << GetRegisterContext().GetWatchpointHitAddress(wp_index); m_stop_description = ostr.str(); @@ -139,21 +141,9 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info, llvm_unreachable("unhandled StateType!"); } -NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() { - // Return the register context if we already created it. - if (m_reg_context_sp) - return m_reg_context_sp; - - ArchSpec target_arch; - if (!m_process.GetArchitecture(target_arch)) - return NativeRegisterContextSP(); - - const uint32_t concrete_frame_idx = 0; - m_reg_context_sp.reset( - NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD( - target_arch, *this, concrete_frame_idx)); - - return m_reg_context_sp; +NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() { + assert(m_reg_context_up); +return *m_reg_context_up; } Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, @@ -165,8 +155,7 @@ Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size, Status error = RemoveWatchpoint(addr); if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags); + uint32_t wp_index = GetRegisterContext().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}); @@ -179,7 +168,7 @@ Status NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) { return Status(); uint32_t wp_index = wp->second; m_watchpoint_index_map.erase(wp); - if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index)) + if (GetRegisterContext().ClearHardwareWatchpoint(wp_index)) return Status(); return Status("Clearing hardware watchpoint failed."); } @@ -193,8 +182,7 @@ Status NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr, if (error.Fail()) return error; - NativeRegisterContextSP reg_ctx = GetRegisterContext(); - uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size); + uint32_t bp_index = GetRegisterContext().SetHardwareBreakpoint(addr, size); if (bp_index == LLDB_INVALID_INDEX32) return Status("Setting hardware breakpoint failed."); @@ -209,7 +197,7 @@ Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) { return Status(); uint32_t bp_index = bp->second; - if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) { + if (GetRegisterContext().ClearHardwareBreakpoint(bp_index)) { m_hw_break_index_map.erase(bp); return Status(); } diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h index 1e3f587be5f5..72426244c112 100644 --- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -37,7 +37,7 @@ public: bool GetStopReason(ThreadStopInfo &stop_info, std::string &description) override; - NativeRegisterContextSP GetRegisterContext() override; + NativeRegisterContext& GetRegisterContext() override; Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override; @@ -67,7 +67,7 @@ private: // --------------------------------------------------------------------- lldb::StateType m_state; ThreadStopInfo m_stop_info; - NativeRegisterContextSP m_reg_context_sp; + std::unique_ptr<NativeRegisterContext> m_reg_context_up; std::string m_stop_description; using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>; WatchpointIndexMap m_watchpoint_index_map; diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt index bda0ad626f6f..3780fb5e4c18 100644 --- a/source/Plugins/Process/Utility/CMakeLists.txt +++ b/source/Plugins/Process/Utility/CMakeLists.txt @@ -39,11 +39,13 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN 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 diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 1a4511a82230..61e5bf4481d6 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -9,14 +9,10 @@ #include "DynamicRegisterInfo.h" -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/StreamFile.h" #include "lldb/DataFormatters/FormatManager.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/StringExtractor.h" #include "lldb/Utility/StructuredData.h" diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 4e1f10c6ae18..5c51a035ec66 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -64,7 +64,7 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, options.SetTimeout(std::chrono::milliseconds(500)); options.SetTrapExceptions(false); - addr_t prot_arg, flags_arg = 0; + addr_t prot_arg; if (prot == eMmapProtNone) prot_arg = PROT_NONE; else { @@ -77,11 +77,6 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, prot_arg |= PROT_WRITE; } - const ArchSpec arch = process->GetTarget().GetArchitecture(); - flags_arg = - process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch, - flags); - AddressRange mmap_range; if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) { @@ -89,7 +84,10 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::addr_t args[] = {addr, length, prot_arg, flags_arg, fd, offset}; + const ArchSpec arch = process->GetTarget().GetArchitecture(); + MmapArgList args = + process->GetTarget().GetPlatform()->GetMmapArgumentList( + arch, addr, length, prot_arg, flags, fd, offset); lldb::ThreadPlanSP call_plan_sp( new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), clang_void_ptr_type, args, options)); diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp index 0b1814362425..3a9d497711c0 100644 --- a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.cpp @@ -14,9 +14,9 @@ using namespace lldb_private; NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo( - NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &thread, RegisterInfoInterface *register_info_interface) - : NativeRegisterContext(thread, concrete_frame_idx), + : NativeRegisterContext(thread), m_register_info_interface_up(register_info_interface) { assert(register_info_interface && "null register_info_interface"); } diff --git a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h index c1b597462b60..8f2e4409105f 100644 --- a/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h +++ b/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -23,7 +23,7 @@ public: /// of the register_info_interface pointer. /// NativeRegisterContextRegisterInfo( - NativeThreadProtocol &thread, uint32_t concrete_frame_idx, + NativeThreadProtocol &thread, RegisterInfoInterface *register_info_interface); uint32_t GetRegisterCount() const override; diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 0c36f1a8346c..344c08965fad 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -426,7 +426,7 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, + value.SetBytes(fpu.v[reg].bytes.buffer, reg_info->byte_size, endian::InlHostByteOrder()); break; @@ -618,7 +618,7 @@ bool RegisterContextDarwin_arm64::WriteRegister(const RegisterInfo *reg_info, case fpu_v29: case fpu_v30: case fpu_v31: - ::memcpy(fpu.v[reg].bytes, value.GetBytes(), value.GetByteSize()); + ::memcpy(fpu.v[reg].bytes.buffer, value.GetBytes(), value.GetByteSize()); break; case fpu_fpsr: diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index 2d1fe0555b58..4a0e50947ee7 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -78,7 +78,7 @@ public: }; struct VReg { - uint8_t bytes[16]; + llvm::AlignedCharArray<16, 16> bytes; }; // mirrors <mach/arm/thread_status.h> arm_neon_state64_t diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index bd73a29e0871..5435a02433ab 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1517,8 +1517,8 @@ RegisterContextLLDB::SavedLocationForRegister( dwarfexpr.SetRegisterKind(unwindplan_registerkind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, - nullptr, result, &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + &error)) { addr_t val; val = result.GetScalar().ULongLong(); if (unwindplan_regloc.IsDWARFExpression()) { @@ -1827,8 +1827,8 @@ bool RegisterContextLLDB::ReadCFAValueForRow( dwarfexpr.SetRegisterKind(row_register_kind); Value result; Status error; - if (dwarfexpr.Evaluate(&exe_ctx, nullptr, nullptr, this, 0, nullptr, - nullptr, result, &error)) { + if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result, + &error)) { cfa_value = result.GetScalar().ULongLong(); UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64, diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp index a4cf07710194..71d35bbd3938 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp @@ -50,22 +50,30 @@ int RegisterContextMach_arm::DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) { int RegisterContextMach_arm::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_arm::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_arm::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } int RegisterContextMach_arm::DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) { - return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<DBG *>(&dbg)), + DBGWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp index 959149edbc3e..5a260d5de1d5 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp @@ -43,17 +43,23 @@ int RegisterContextMach_i386::DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) { int RegisterContextMach_i386::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_i386::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_i386::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp index 522b73a2888e..0180879d51ee 100644 --- a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp @@ -46,17 +46,23 @@ int RegisterContextMach_x86_64::DoReadEXC(lldb::tid_t tid, int flavor, int RegisterContextMach_x86_64::DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) { - return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<GPR *>(&gpr)), + GPRWordCount); } int RegisterContextMach_x86_64::DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) { - return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<FPU *>(&fpu)), + FPUWordCount); } int RegisterContextMach_x86_64::DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) { - return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount); + return ::thread_set_state( + tid, flavor, reinterpret_cast<thread_state_t>(const_cast<EXC *>(&exc)), + EXCWordCount); } #endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp new file mode 100644 index 000000000000..de410f063b53 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp @@ -0,0 +1,216 @@ +//===-- RegisterContextPOSIX_ppc64le.cpp -------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <cstring> +#include <errno.h> +#include <stdint.h> + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "llvm/Support/Compiler.h" + +#include "Plugins/Process/elf-core/ProcessElfCore.h" +#include "RegisterContextPOSIX_ppc64le.h" + +using namespace lldb_private; +using namespace lldb; + +static const uint32_t g_gpr_regnums[] = { + 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, +}; + +static const uint32_t g_fpr_regnums[] = { + 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, +}; + +static const uint32_t g_vmx_regnums[] = { + 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, +}; + +static const uint32_t g_vsx_regnums[] = { + 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, +}; + +// 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}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_ppc64le, + g_fpr_regnums}, + {"Altivec/VMX Registers", "vmx", k_num_vmx_registers_ppc64le, + g_vmx_regnums}, + {"VSX Registers", "vsx", k_num_vsx_registers_ppc64le, g_vsx_regnums}, +}; + +bool RegisterContextPOSIX_ppc64le::IsGPR(unsigned reg) { + return (reg <= k_last_gpr_ppc64le); // GPR's come first. +} + +bool RegisterContextPOSIX_ppc64le::IsFPR(unsigned reg) { + return (reg >= k_first_fpr_ppc64le) && (reg <= k_last_fpr_ppc64le); +} + +bool RegisterContextPOSIX_ppc64le::IsVMX(unsigned reg) { + return (reg >= k_first_vmx_ppc64le) && (reg <= k_last_vmx_ppc64le); +} + +bool RegisterContextPOSIX_ppc64le::IsVSX(unsigned reg) { + return (reg >= k_first_vsx_ppc64le) && (reg <= k_last_vsx_ppc64le); +} + +RegisterContextPOSIX_ppc64le::RegisterContextPOSIX_ppc64le( + Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) { + m_register_info_ap.reset(register_info); + + ProcessSP base = CalculateProcess(); + if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic()) + return; +} + +void RegisterContextPOSIX_ppc64le::InvalidateAllRegisters() {} + +unsigned RegisterContextPOSIX_ppc64le::GetRegisterOffset(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned RegisterContextPOSIX_ppc64le::GetRegisterSize(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +size_t RegisterContextPOSIX_ppc64le::GetRegisterCount() { + size_t num_registers = k_num_registers_ppc64le; + return num_registers; +} + +size_t RegisterContextPOSIX_ppc64le::GetGPRSize() { + return m_register_info_ap->GetGPRSize(); +} + +const RegisterInfo *RegisterContextPOSIX_ppc64le::GetRegisterInfo() { + // Commonly, this method is overridden and g_register_infos is copied and + // specialized. + // So, use GetRegisterInfo() rather than g_register_infos in this scope. + return m_register_info_ap->GetRegisterInfo(); +} + +const RegisterInfo * +RegisterContextPOSIX_ppc64le::GetRegisterInfoAtIndex(size_t reg) { + if (reg < k_num_registers_ppc64le) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t RegisterContextPOSIX_ppc64le::GetRegisterSetCount() { + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet *RegisterContextPOSIX_ppc64le::GetRegisterSet(size_t set) { + if (IsRegisterSetAvailable(set)) + return &g_reg_sets_ppc64le[set]; + else + return NULL; +} + +const char *RegisterContextPOSIX_ppc64le::GetRegisterName(unsigned reg) { + assert(reg < k_num_registers_ppc64le && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +lldb::ByteOrder RegisterContextPOSIX_ppc64le::GetByteOrder() { + // Get the target process whose privileged thread was used for the register + // read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +bool RegisterContextPOSIX_ppc64le::IsRegisterSetAvailable(size_t set_index) { + size_t num_sets = k_num_register_sets; + + return (set_index < num_sets); +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t RegisterContextPOSIX_ppc64le::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; +} diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h new file mode 100644 index 000000000000..1070b4dea405 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h @@ -0,0 +1,82 @@ +//===-- RegisterContextPOSIX_ppc64le.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_RegisterContextPOSIX_ppc64le_h_ +#define liblldb_RegisterContextPOSIX_ppc64le_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" +#include "RegisterInfoInterface.h" +#include "Utility/PPC64LE_DWARF_Registers.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" + +class RegisterContextPOSIX_ppc64le : public lldb_private::RegisterContext { +public: + RegisterContextPOSIX_ppc64le( + lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + + const char *GetRegisterName(unsigned reg); + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + +protected: + // 64-bit general purpose registers. + uint64_t m_gpr_ppc64le[k_num_gpr_registers_ppc64le]; + + // floating-point registers including extended register. + uint64_t m_fpr_ppc64le[k_num_fpr_registers_ppc64le]; + + // VMX registers. + uint64_t m_vmx_ppc64le[k_num_vmx_registers_ppc64le * 2]; + + // VSX registers. + uint64_t m_vsx_ppc64le[k_num_vsx_registers_ppc64le * 2]; + + std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; + + // Determines if an extended register set is supported on the processor + // running the inferior process. + virtual bool IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + bool IsVMX(unsigned reg); + + bool IsVSX(unsigned reg); + + lldb::ByteOrder GetByteOrder(); +}; + +#endif // liblldb_RegisterContextPOSIX_ppc64le_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 5e1bf35356b8..41cec8add987 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -365,12 +365,6 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( 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.xstate.xsave; - m_iovec.iov_len = sizeof(m_fpr.xstate.xsave); - ::memset(&m_fpr, 0, sizeof(FPR)); m_fpr_type = eNotValid; @@ -481,19 +475,19 @@ bool RegisterContextPOSIX_x86::CopyYMMtoXSTATE(uint32_t reg, return false; if (byte_order == eByteOrderLittle) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::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.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::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 == eByteOrderBig) { - ::memcpy(m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + ::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.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + ::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; } @@ -508,20 +502,20 @@ bool RegisterContextPOSIX_x86::CopyXSTATEtoYMM(uint32_t reg, if (byte_order == eByteOrderLittle) { ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } if (byte_order == eByteOrderBig) { ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes + sizeof(XMMReg), - m_fpr.xstate.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, + m_fpr.fxsave.xmm[reg - m_reg_info.first_ymm].bytes, sizeof(XMMReg)); ::memcpy(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes, - m_fpr.xstate.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, + m_fpr.xsave.ymmh[reg - m_reg_info.first_ymm].bytes, sizeof(YMMHReg)); return true; } diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index aa689273f218..ca71a6f272f8 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -149,9 +149,9 @@ protected: RegInfo m_reg_info; FPRType m_fpr_type; // determines the type of data stored by union FPR, if any. - FPR m_fpr; // floating-point registers including extended register sets. - IOVEC m_iovec; // wrapper for xsave. - YMM m_ymm_set; // copy of ymmh and xmm register halves. + lldb_private::FPR m_fpr; // floating-point registers including extended + // register sets. + lldb_private::YMM m_ymm_set; // copy of ymmh and xmm register halves. std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux) diff --git a/source/Plugins/Process/Utility/RegisterContext_mips.h b/source/Plugins/Process/Utility/RegisterContext_mips.h index 565747cb4bd7..da470bd82732 100644 --- a/source/Plugins/Process/Utility/RegisterContext_mips.h +++ b/source/Plugins/Process/Utility/RegisterContext_mips.h @@ -241,11 +241,6 @@ enum { dwarf_config5_mips64, }; -struct IOVEC_mips { - void *iov_base; - size_t iov_len; -}; - // GP registers struct GPR_linux_mips { uint64_t zero; diff --git a/source/Plugins/Process/Utility/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h index 5f6fc295a15c..6146dcaf7e5a 100644 --- a/source/Plugins/Process/Utility/RegisterContext_x86.h +++ b/source/Plugins/Process/Utility/RegisterContext_x86.h @@ -13,8 +13,10 @@ #include <cstddef> #include <cstdint> +#include "llvm/ADT/BitmaskEnum.h" #include "llvm/Support/Compiler.h" +namespace lldb_private { //--------------------------------------------------------------------------- // i386 ehframe, dwarf regnums //--------------------------------------------------------------------------- @@ -313,13 +315,28 @@ struct MPX { LLVM_PACKED_START struct XSAVE_HDR { - uint64_t xstate_bv; // OS enabled xstate mask to determine the extended states + enum class XFeature : uint64_t { + FP = 1, + SSE = FP << 1, + YMM = SSE << 1, + BNDREGS = YMM << 1, + BNDCSR = BNDREGS << 1, + OPMASK = BNDCSR << 1, + ZMM_Hi256 = OPMASK << 1, + Hi16_ZMM = ZMM_Hi256 << 1, + PT = Hi16_ZMM << 1, + PKRU = PT << 1, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ PKRU) + }; + + XFeature xstate_bv; // OS enabled xstate mask to determine the extended states // supported by the processor - uint64_t xcomp_bv; // Mask to indicate the format of the XSAVE area and of + XFeature xcomp_bv; // Mask to indicate the format of the XSAVE area and of // the XRSTOR instruction uint64_t reserved1[1]; uint64_t reserved2[5]; }; +static_assert(sizeof(XSAVE_HDR) == 64, "XSAVE_HDR layout incorrect"); LLVM_PACKED_END // x86 extensions to FXSAVE (i.e. for AVX and MPX processors) @@ -338,21 +355,13 @@ struct LLVM_ALIGNAS(64) XSAVE { LLVM_PACKED_END // Floating-point registers -struct FPR { - // Thread state for the floating-point unit of the processor read by ptrace. - union XSTATE { - FXSAVE fxsave; // Generic floating-point registers. - XSAVE xsave; // x86 extended processor state. - } xstate; +union FPR { + FXSAVE fxsave; // Generic floating-point registers. + XSAVE xsave; // x86 extended processor state. }; -//--------------------------------------------------------------------------- -// ptrace PTRACE_GETREGSET, PTRACE_SETREGSET structure -//--------------------------------------------------------------------------- +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); -struct IOVEC { - void *iov_base; // pointer to XSAVE - size_t iov_len; // sizeof(XSAVE) -}; +} // namespace lldb_private #endif diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 74d5d6e50208..1894b5368122 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -10,10 +10,9 @@ #ifndef lldb_RegisterInfoInterface_h #define lldb_RegisterInfoInterface_h -#include <vector> - -#include "lldb/Core/ArchSpec.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/lldb-private-types.h" +#include <vector> namespace lldb_private { diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp new file mode 100644 index 000000000000..e5e7350fe68a --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -0,0 +1,66 @@ +//===-- RegisterInfoPOSIX_ppc64le.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include <cassert> +#include <stddef.h> +#include <vector> + +#include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterInfoPOSIX_ppc64le.h" + +//----------------------------------------------------------------------------- +// Include RegisterInfoPOSIX_ppc64le to declare our g_register_infos_ppc64le +//----------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT +#include "RegisterInfos_ppc64le.h" +#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +static const lldb_private::RegisterInfo * +GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64le: + return g_register_infos_ppc64le; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } +} + +static uint32_t +GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { + switch (target_arch.GetMachine()) { + case llvm::Triple::ppc64le: + return static_cast<uint32_t>(sizeof(g_register_infos_ppc64le) / + sizeof(g_register_infos_ppc64le[0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +RegisterInfoPOSIX_ppc64le::RegisterInfoPOSIX_ppc64le( + const lldb_private::ArchSpec &target_arch) + : lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p(GetRegisterInfoPtr(target_arch)), + m_register_info_count(GetRegisterInfoCount(target_arch)) {} + +size_t RegisterInfoPOSIX_ppc64le::GetGPRSize() const { + return sizeof(GPR); +} + +const lldb_private::RegisterInfo * +RegisterInfoPOSIX_ppc64le::GetRegisterInfo() const { + return m_register_info_p; +} + +uint32_t RegisterInfoPOSIX_ppc64le::GetRegisterCount() const { + return m_register_info_count; +} diff --git a/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h new file mode 100644 index 000000000000..411ab05c2b13 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h @@ -0,0 +1,32 @@ +//===-- RegisterInfoPOSIX_ppc64le.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_RegisterContextLinux_ppc64le_H_ +#define liblldb_RegisterContextLinux_ppc64le_H_ + +#include "RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" + +class RegisterInfoPOSIX_ppc64le : public lldb_private::RegisterInfoInterface { +public: + RegisterInfoPOSIX_ppc64le(const lldb_private::ArchSpec &target_arch); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + uint32_t m_register_info_count; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h index 8597d0c39dc4..ffdc4d0d116b 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -27,19 +27,19 @@ // Based on DNBArchImplI386.cpp from debugserver #define YMM_OFFSET(reg_index) \ (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, fxsave) + \ LLVM_EXTENSION offsetof(FXSAVE, xmm[7]) + sizeof(XMMReg) + \ (32 * reg_index)) -#define BNDR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) +#define BNDR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) -#define BNDC_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, i387) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) +#define BNDC_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, i387) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) // Number of bytes needed to represent a FPR. #if !defined(FPR_SIZE) diff --git a/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h new file mode 100644 index 000000000000..bffa7a1d8b63 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h @@ -0,0 +1,476 @@ +//===-- RegisterInfos_ppc64le.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT + +// C Includes +#include <stddef.h> + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) (offsetof(GPR, regname)) +#define FPR_OFFSET(regname) (offsetof(FPR, regname) + sizeof(GPR)) +#define VMX_OFFSET(regname) (offsetof(VMX, regname) + sizeof(GPR) + sizeof(FPR)) +#define VSX_OFFSET(regname) \ + (offsetof(VSX, regname) + sizeof(GPR) + sizeof(FPR) + sizeof(VMX)) +#define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname)) + +#include "Utility/PPC64LE_DWARF_Registers.h" +#include "lldb-ppc64le-register-enums.h" + +// Note that the size and offset will be updated by platform-specific classes. +#define DEFINE_GPR(reg, alt, lldb_kind) \ + { \ + #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le,\ + ppc64le_dwarf::dwarf_##reg##_ppc64le,\ + lldb_kind, \ + LLDB_INVALID_REGNUM, \ + gpr_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_FPR(reg, alt, lldb_kind) \ + { \ +#reg, alt, 8, FPR_OFFSET(reg), lldb::eEncodingIEEE754, lldb::eFormatFloat, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + fpr_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_VMX(reg, lldb_kind) \ + { \ +#reg, NULL, 16, VMX_OFFSET(reg), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt32, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + vmx_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } +#define DEFINE_VSX(reg, lldb_kind) \ + { \ +#reg, NULL, 16, VSX_OFFSET(reg), lldb::eEncodingVector, \ + lldb::eFormatVectorOfUInt32, \ + {ppc64le_dwarf::dwarf_##reg##_ppc64le, \ + ppc64le_dwarf::dwarf_##reg##_ppc64le, lldb_kind, LLDB_INVALID_REGNUM, \ + vsx_##reg##_ppc64le }, \ + NULL, NULL, NULL, 0 \ + } + +// General purpose registers. +// EH_Frame, Generic, Process Plugin +#define POWERPC_REGS \ + DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM) \ + , DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \ + DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r3, "arg1", LLDB_REGNUM_GENERIC_ARG1), \ + DEFINE_GPR(r4, "arg2", LLDB_REGNUM_GENERIC_ARG2), \ + DEFINE_GPR(r5, "arg3", LLDB_REGNUM_GENERIC_ARG3), \ + DEFINE_GPR(r6, "arg4", LLDB_REGNUM_GENERIC_ARG4), \ + DEFINE_GPR(r7, "arg5", LLDB_REGNUM_GENERIC_ARG5), \ + DEFINE_GPR(r8, "arg6", LLDB_REGNUM_GENERIC_ARG6), \ + DEFINE_GPR(r9, "arg7", LLDB_REGNUM_GENERIC_ARG7), \ + DEFINE_GPR(r10, "arg8", LLDB_REGNUM_GENERIC_ARG8), \ + DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \ + DEFINE_GPR(msr, "msr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(origr3, "orig_r3", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \ + DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \ + DEFINE_GPR(softe, "softe", LLDB_INVALID_REGNUM), \ + DEFINE_GPR(trap, "trap", LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f0, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f1, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f2, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f3, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f4, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f5, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f6, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f7, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f8, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f9, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f10, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f11, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f12, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f13, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f14, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f15, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f16, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f17, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f18, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f19, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f20, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f21, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f22, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f23, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f24, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f25, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f26, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f27, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f28, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f29, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f30, NULL, LLDB_INVALID_REGNUM), \ + DEFINE_FPR(f31, NULL, LLDB_INVALID_REGNUM), \ + {"fpscr", \ + NULL, \ + 8, \ + FPR_OFFSET(fpscr), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_fpscr_ppc64le, \ + ppc64le_dwarf::dwarf_fpscr_ppc64le, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, fpr_fpscr_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + DEFINE_VMX(vr0, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr1, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr2, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr3, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr4, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr5, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr6, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr7, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr8, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr9, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr10, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr11, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr12, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr13, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr14, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr15, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr16, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr17, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr18, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr19, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr20, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr21, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr22, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr23, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr24, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr25, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr26, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr27, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr28, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr29, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr30, LLDB_INVALID_REGNUM), \ + DEFINE_VMX(vr31, LLDB_INVALID_REGNUM), \ + {"vscr", \ + NULL, \ + 4, \ + VMX_OFFSET(vscr), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_vscr_ppc64le, ppc64le_dwarf::dwarf_vscr_ppc64le, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + {"vrsave", \ + NULL, \ + 4, \ + VMX_OFFSET(vrsave), \ + lldb::eEncodingUint, \ + lldb::eFormatHex, \ + {ppc64le_dwarf::dwarf_vrsave_ppc64le, \ + ppc64le_dwarf::dwarf_vrsave_ppc64le, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, vmx_vrsave_ppc64le}, \ + NULL, \ + NULL, \ + NULL, \ + 0}, \ + DEFINE_VSX(vs0, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs1, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs2, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs3, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs4, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs5, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs6, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs7, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs8, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs9, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs10, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs11, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs12, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs13, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs14, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs15, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs16, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs17, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs18, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs19, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs20, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs21, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs22, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs23, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs24, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs25, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs26, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs27, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs28, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs29, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs30, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs31, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs32, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs33, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs34, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs35, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs36, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs37, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs38, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs39, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs40, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs41, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs42, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs43, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs44, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs45, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs46, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs47, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs48, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs49, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs50, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs51, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs52, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs53, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs54, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs55, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs56, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs57, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs58, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs59, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs50, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs61, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs62, LLDB_INVALID_REGNUM), \ + DEFINE_VSX(vs63, LLDB_INVALID_REGNUM), /* */ + +typedef struct _GPR { + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + uint64_t r16; + uint64_t r17; + uint64_t r18; + uint64_t r19; + uint64_t r20; + uint64_t r21; + uint64_t r22; + uint64_t r23; + uint64_t r24; + uint64_t r25; + uint64_t r26; + uint64_t r27; + uint64_t r28; + uint64_t r29; + uint64_t r30; + uint64_t r31; + uint64_t pc; + uint64_t msr; + uint64_t origr3; + uint64_t ctr; + uint64_t lr; + uint64_t xer; + uint64_t cr; + uint64_t softe; + uint64_t trap; + uint64_t pad[3]; +} GPR; + +typedef struct _FPR { + uint64_t f0; + uint64_t f1; + uint64_t f2; + uint64_t f3; + uint64_t f4; + uint64_t f5; + uint64_t f6; + uint64_t f7; + uint64_t f8; + uint64_t f9; + uint64_t f10; + uint64_t f11; + uint64_t f12; + uint64_t f13; + uint64_t f14; + uint64_t f15; + uint64_t f16; + uint64_t f17; + uint64_t f18; + uint64_t f19; + uint64_t f20; + uint64_t f21; + uint64_t f22; + uint64_t f23; + uint64_t f24; + uint64_t f25; + uint64_t f26; + uint64_t f27; + uint64_t f28; + uint64_t f29; + uint64_t f30; + uint64_t f31; + uint64_t fpscr; +} FPR; + +typedef struct _VMX { + uint32_t vr0[4]; + uint32_t vr1[4]; + uint32_t vr2[4]; + uint32_t vr3[4]; + uint32_t vr4[4]; + uint32_t vr5[4]; + uint32_t vr6[4]; + uint32_t vr7[4]; + uint32_t vr8[4]; + uint32_t vr9[4]; + uint32_t vr10[4]; + uint32_t vr11[4]; + uint32_t vr12[4]; + uint32_t vr13[4]; + uint32_t vr14[4]; + uint32_t vr15[4]; + uint32_t vr16[4]; + uint32_t vr17[4]; + uint32_t vr18[4]; + uint32_t vr19[4]; + uint32_t vr20[4]; + uint32_t vr21[4]; + uint32_t vr22[4]; + uint32_t vr23[4]; + uint32_t vr24[4]; + uint32_t vr25[4]; + uint32_t vr26[4]; + uint32_t vr27[4]; + uint32_t vr28[4]; + uint32_t vr29[4]; + uint32_t vr30[4]; + uint32_t vr31[4]; + uint32_t pad[2]; + uint32_t vscr[2]; + uint32_t vrsave; +} VMX; + +typedef struct _VSX { + uint32_t vs0[4]; + uint32_t vs1[4]; + uint32_t vs2[4]; + uint32_t vs3[4]; + uint32_t vs4[4]; + uint32_t vs5[4]; + uint32_t vs6[4]; + uint32_t vs7[4]; + uint32_t vs8[4]; + uint32_t vs9[4]; + uint32_t vs10[4]; + uint32_t vs11[4]; + uint32_t vs12[4]; + uint32_t vs13[4]; + uint32_t vs14[4]; + uint32_t vs15[4]; + uint32_t vs16[4]; + uint32_t vs17[4]; + uint32_t vs18[4]; + uint32_t vs19[4]; + uint32_t vs20[4]; + uint32_t vs21[4]; + uint32_t vs22[4]; + uint32_t vs23[4]; + uint32_t vs24[4]; + uint32_t vs25[4]; + uint32_t vs26[4]; + uint32_t vs27[4]; + uint32_t vs28[4]; + uint32_t vs29[4]; + uint32_t vs30[4]; + uint32_t vs31[4]; + uint32_t vs32[4]; + uint32_t vs33[4]; + uint32_t vs34[4]; + uint32_t vs35[4]; + uint32_t vs36[4]; + uint32_t vs37[4]; + uint32_t vs38[4]; + uint32_t vs39[4]; + uint32_t vs40[4]; + uint32_t vs41[4]; + uint32_t vs42[4]; + uint32_t vs43[4]; + uint32_t vs44[4]; + uint32_t vs45[4]; + uint32_t vs46[4]; + uint32_t vs47[4]; + uint32_t vs48[4]; + uint32_t vs49[4]; + uint32_t vs50[4]; + uint32_t vs51[4]; + uint32_t vs52[4]; + uint32_t vs53[4]; + uint32_t vs54[4]; + uint32_t vs55[4]; + uint32_t vs56[4]; + uint32_t vs57[4]; + uint32_t vs58[4]; + uint32_t vs59[4]; + uint32_t vs60[4]; + uint32_t vs61[4]; + uint32_t vs62[4]; + uint32_t vs63[4]; +} VSX; + +static lldb_private::RegisterInfo g_register_infos_ppc64le[] = { + POWERPC_REGS +}; + +static_assert((sizeof(g_register_infos_ppc64le) / + sizeof(g_register_infos_ppc64le[0])) == + k_num_registers_ppc64le, + "g_register_infos_powerpc64 has wrong number of register infos"); + +#undef DEFINE_FPR +#undef DEFINE_GPR +#undef DEFINE_VMX +#undef DEFINE_VSX + +#endif // DECLARE_REGISTER_INFOS_PPC64LE_STRUCT diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h index 8861ecd66806..651536cb6045 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h @@ -7,11 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" -#include <cstddef> -#include <cstdint> - -// Project includes +// This file is meant to be textually included. Do not #include modular +// headers here. // Computes the offset of the given GPR in the user data area. #define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) @@ -19,25 +16,25 @@ // Computes the offset of the given FPR in the extended data area. #define FPR_OFFSET(regname) \ (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, fxsave) + \ LLVM_EXTENSION offsetof(FXSAVE, regname)) // Computes the offset of the YMM register assembled from register halves. // Based on DNBArchImplX86_64.cpp from debugserver #define YMM_OFFSET(reg_index) \ (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) -#define BNDR_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) +#define BNDR_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index])) -#define BNDC_OFFSET(reg_index) \ - (LLVM_EXTENSION offsetof(UserArea, fpr) + \ - LLVM_EXTENSION offsetof(FPR, xstate) + \ - LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) +#define BNDC_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xsave) + \ + LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index])) #ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 435f3d18c062..3e860874183c 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -14,7 +14,6 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp index f907735d8f58..d831011cb661 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp @@ -7,11 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -19,6 +14,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" #include "RegisterContextMacOSXFrameBackchain.h" @@ -85,8 +81,6 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386( if (process == NULL) return 0; - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - struct Frame_i386 { uint32_t fp; uint32_t pc; @@ -179,8 +173,6 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64( StackFrame *first_frame = exe_ctx.GetFramePtr(); - std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair; - struct Frame_x86_64 { uint64_t fp; uint64_t pc; diff --git a/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h b/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h new file mode 100644 index 000000000000..675804d13268 --- /dev/null +++ b/source/Plugins/Process/Utility/lldb-ppc64le-register-enums.h @@ -0,0 +1,210 @@ +//===-- lldb-ppc64le-register-enums.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_ppc64le_register_enums_h +#define lldb_ppc64le_register_enums_h + +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +// --------------------------------------------------------------------------- +// Internal codes for all ppc64le registers. +// --------------------------------------------------------------------------- +enum { + k_first_gpr_ppc64le, + gpr_r0_ppc64le = k_first_gpr_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, + k_last_gpr_ppc64le = gpr_trap_ppc64le, + + k_first_fpr_ppc64le, + fpr_f0_ppc64le = k_first_fpr_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, + k_last_fpr_ppc64le = fpr_fpscr_ppc64le, + + k_first_vmx_ppc64le, + vmx_vr0_ppc64le = k_first_vmx_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, + k_last_vmx_ppc64le = vmx_vrsave_ppc64le, + + k_first_vsx_ppc64le, + vsx_vs0_ppc64le = k_first_vsx_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, + k_last_vsx_ppc64le = vsx_vs63_ppc64le, + + k_num_registers_ppc64le, + k_num_gpr_registers_ppc64le = k_last_gpr_ppc64le - k_first_gpr_ppc64le + 1, + k_num_fpr_registers_ppc64le = k_last_fpr_ppc64le - k_first_fpr_ppc64le + 1, + k_num_vmx_registers_ppc64le = k_last_vmx_ppc64le - k_first_vmx_ppc64le + 1, + k_num_vsx_registers_ppc64le = k_last_vsx_ppc64le - k_first_vsx_ppc64le + 1, +}; + +#endif // #ifndef lldb_ppc64le_register_enums_h diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt index c7ffae695320..3082c73f6dda 100644 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/source/Plugins/Process/elf-core/CMakeLists.txt @@ -7,8 +7,10 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN RegisterContextPOSIXCore_arm64.cpp RegisterContextPOSIXCore_mips64.cpp RegisterContextPOSIXCore_powerpc.cpp + RegisterContextPOSIXCore_ppc64le.cpp RegisterContextPOSIXCore_s390x.cpp RegisterContextPOSIXCore_x86_64.cpp + RegisterUtilities.cpp LINK_LIBS lldbCore diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 71eb6437ceed..7d6a0c9ad2df 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -32,8 +32,7 @@ #include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" - -// Project includes +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "ProcessElfCore.h" #include "ThreadElfCore.h" @@ -101,10 +100,7 @@ bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp, ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) - : Process(target_sp, listener_sp), m_core_module_sp(), - m_core_file(core_file), m_dyld_plugin_name(), - m_os(llvm::Triple::UnknownOS), m_thread_data_valid(false), - m_thread_data(), m_core_aranges() {} + : Process(target_sp, listener_sp), m_core_file(core_file) {} //---------------------------------------------------------------------- // Destructor @@ -193,9 +189,8 @@ Status ProcessElfCore::DoLoadCore() { // Parse thread contexts and auxv structure if (header->p_type == llvm::ELF::PT_NOTE) { - error = ParseThreadContextsFromNoteSegment(header, data); - if (error.Fail()) - return error; + if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data)) + return Status(std::move(error)); } // PT_LOAD segments contains address map if (header->p_type == llvm::ELF::PT_LOAD) { @@ -404,7 +399,6 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, void ProcessElfCore::Clear() { m_thread_list.Clear(); - m_os = llvm::Triple::UnknownOS; SetUnixSignals(std::make_shared<UnixSignals>()); } @@ -427,43 +421,10 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() { return LLDB_INVALID_ADDRESS; } -/// Core files PT_NOTE segment descriptor types -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_TASKSTRUCT, - NT_PLATFORM, - NT_AUXV, - NT_FILE = 0x46494c45, - NT_PRXFPREG = 0x46e62b7f, - NT_SIGINFO = 0x53494749, - NT_OPENBSD_PROCINFO = 10, - NT_OPENBSD_AUXV = 11, - NT_OPENBSD_REGS = 20, - NT_OPENBSD_FPREGS = 21, -}; - -namespace FREEBSD { - -enum { - NT_PRSTATUS = 1, - NT_FPREGSET, - NT_PRPSINFO, - NT_THRMISC = 7, - NT_PROCSTAT_AUXV = 16, - NT_PPC_VMX = 0x100 -}; -} - -namespace NETBSD { - -enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; -} - // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. -static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, - ArchSpec &arch) { +static void ParseFreeBSDPrStatus(ThreadData &thread_data, + const DataExtractor &data, + const ArchSpec &arch) { lldb::offset_t offset = 0; bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || arch.GetMachine() == llvm::Triple::mips64 || @@ -492,12 +453,8 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, thread_data.gpregset = DataExtractor(data, offset, len); } -static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) { - lldb::offset_t offset = 0; - thread_data.name = data.GetCStr(&offset, 20); -} - -static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { +static void ParseNetBSDProcInfo(ThreadData &thread_data, + const DataExtractor &data) { lldb::offset_t offset = 0; int version = data.GetU32(&offset); @@ -508,7 +465,8 @@ static void ParseNetBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { thread_data.signo = data.GetU32(&offset); } -static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { +static void ParseOpenBSDProcInfo(ThreadData &thread_data, + const DataExtractor &data) { lldb::offset_t offset = 0; int version = data.GetU32(&offset); @@ -519,202 +477,263 @@ static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data) { thread_data.signo = data.GetU32(&offset); } -/// Parse Thread context from PT_NOTE segment and store it in the thread list -/// Notes: -/// 1) A PT_NOTE segment is composed of one or more NOTE entries. -/// 2) NOTE Entry contains a standard header followed by variable size data. -/// (see ELFNote structure) -/// 3) A Thread Context in a core file usually described by 3 NOTE entries. -/// a) NT_PRSTATUS - Register context -/// b) NT_PRPSINFO - Process info(pid..) -/// c) NT_FPREGSET - Floating point registers -/// 4) The NOTE entries can be in any order -/// 5) If a core file contains multiple thread contexts then there is two data -/// forms -/// a) Each thread context(2 or more NOTE entries) contained in its own -/// segment (PT_NOTE) -/// b) All thread context is stored in a single segment(PT_NOTE). -/// This case is little tricker since while parsing we have to find where -/// the -/// new thread starts. The current implementation marks beginning of -/// new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry. -/// For case (b) there may be either one NT_PRPSINFO per thread, or a single -/// one that applies to all threads (depending on the platform type). -Status ProcessElfCore::ParseThreadContextsFromNoteSegment( - const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { - assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); - +llvm::Expected<std::vector<CoreNote>> +ProcessElfCore::parseSegment(const DataExtractor &segment) { lldb::offset_t offset = 0; - std::unique_ptr<ThreadData> thread_data(new ThreadData); + std::vector<CoreNote> result; + + while (offset < segment.GetByteSize()) { + ELFNote note = ELFNote(); + if (!note.Parse(segment, &offset)) + return llvm::make_error<llvm::StringError>( + "Unable to parse note segment", llvm::inconvertibleErrorCode()); + + size_t note_start = offset; + size_t note_size = llvm::alignTo(note.n_descsz, 4); + DataExtractor note_data(segment, note_start, note_size); + + result.push_back({note, note_data}); + offset += note_size; + } + + return std::move(result); +} + +llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { bool have_prstatus = false; bool have_prpsinfo = false; + ThreadData thread_data; + for (const auto ¬e : notes) { + if (note.info.n_name != "FreeBSD") + continue; + + if ((note.info.n_type == FREEBSD::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == FREEBSD::NT_PRPSINFO && have_prpsinfo)) { + assert(thread_data.gpregset.GetByteSize() > 0); + // Add the new thread to thread list + m_thread_data.push_back(thread_data); + thread_data = ThreadData(); + have_prstatus = false; + have_prpsinfo = false; + } - ArchSpec arch = GetArchitecture(); - ELFLinuxPrPsInfo prpsinfo; - ELFLinuxPrStatus prstatus; - ELFLinuxSigInfo siginfo; - size_t header_size; - size_t len; - Status error; + switch (note.info.n_type) { + case FREEBSD::NT_PRSTATUS: + have_prstatus = true; + ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); + break; + case FREEBSD::NT_PRPSINFO: + have_prpsinfo = true; + break; + case FREEBSD::NT_THRMISC: { + lldb::offset_t offset = 0; + thread_data.name = note.data.GetCStr(&offset, 20); + break; + } + case FREEBSD::NT_PROCSTAT_AUXV: + // FIXME: FreeBSD sticks an int at the beginning of the note + m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4); + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (!have_prstatus) { + return llvm::make_error<llvm::StringError>( + "Could not find NT_PRSTATUS note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - // Loop through the NOTE entires in the segment - while (offset < segment_header->p_filesz) { - ELFNote note = ELFNote(); - note.Parse(segment_data, &offset); +llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { + ThreadData thread_data; + for (const auto ¬e : notes) { + // NetBSD per-thread information is stored in notes named + // "NetBSD-CORE@nnn" so match on the initial part of the string. + if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE")) + continue; + + switch (note.info.n_type) { + case NETBSD::NT_PROCINFO: + ParseNetBSDProcInfo(thread_data, note.data); + break; + case NETBSD::NT_AUXV: + m_auxv = note.data; + break; + + case NETBSD::NT_AMD64_REGS: + if (GetArchitecture().GetMachine() == llvm::Triple::x86_64) + thread_data.gpregset = note.data; + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (thread_data.gpregset.GetByteSize() == 0) { + return llvm::make_error<llvm::StringError>( + "Could not find general purpose registers note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} + +llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) { + ThreadData thread_data; + for (const auto ¬e : notes) { + // OpenBSD per-thread information is stored in notes named + // "OpenBSD@nnn" so match on the initial part of the string. + if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD")) + continue; + + switch (note.info.n_type) { + case OPENBSD::NT_PROCINFO: + ParseOpenBSDProcInfo(thread_data, note.data); + break; + case OPENBSD::NT_AUXV: + m_auxv = note.data; + break; + case OPENBSD::NT_REGS: + thread_data.gpregset = note.data; + break; + default: + thread_data.notes.push_back(note); + break; + } + } + if (thread_data.gpregset.GetByteSize() == 0) { + return llvm::make_error<llvm::StringError>( + "Could not find general purpose registers note in core file.", + llvm::inconvertibleErrorCode()); + } + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - // Beginning of new thread - if ((note.n_type == NT_PRSTATUS && have_prstatus) || - (note.n_type == NT_PRPSINFO && have_prpsinfo)) { - assert(thread_data->gpregset.GetByteSize() > 0); +/// A description of a linux process usually contains the following NOTE +/// entries: +/// - NT_PRPSINFO - General process information like pid, uid, name, ... +/// - NT_SIGINFO - Information about the signal that terminated the process +/// - NT_AUXV - Process auxiliary vector +/// - NT_FILE - Files mapped into memory +/// +/// Additionally, for each thread in the process the core file will contain at +/// least the NT_PRSTATUS note, containing the thread id and general purpose +/// registers. It may include additional notes for other register sets (floating +/// point and vector registers, ...). The tricky part here is that some of these +/// notes have "CORE" in their owner fields, while other set it to "LINUX". +llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) { + const ArchSpec &arch = GetArchitecture(); + bool have_prstatus = false; + bool have_prpsinfo = false; + ThreadData thread_data; + for (const auto ¬e : notes) { + if (note.info.n_name != "CORE" && note.info.n_name != "LINUX") + continue; + + if ((note.info.n_type == LINUX::NT_PRSTATUS && have_prstatus) || + (note.info.n_type == LINUX::NT_PRPSINFO && have_prpsinfo)) { + assert(thread_data.gpregset.GetByteSize() > 0); // Add the new thread to thread list - m_thread_data.push_back(*thread_data); - *thread_data = ThreadData(); + m_thread_data.push_back(thread_data); + thread_data = ThreadData(); have_prstatus = false; have_prpsinfo = false; } - size_t note_start, note_size; - note_start = offset; - note_size = llvm::alignTo(note.n_descsz, 4); - - // Store the NOTE information in the current thread - DataExtractor note_data(segment_data, note_start, note_size); - note_data.SetAddressByteSize( - m_core_module_sp->GetArchitecture().GetAddressByteSize()); - if (note.n_name == "FreeBSD") { - m_os = llvm::Triple::FreeBSD; - switch (note.n_type) { - case FREEBSD::NT_PRSTATUS: - have_prstatus = true; - ParseFreeBSDPrStatus(*thread_data, note_data, arch); - break; - case FREEBSD::NT_FPREGSET: - thread_data->fpregset = note_data; - break; - case FREEBSD::NT_PRPSINFO: - have_prpsinfo = true; - break; - case FREEBSD::NT_THRMISC: - ParseFreeBSDThrMisc(*thread_data, note_data); - break; - case FREEBSD::NT_PROCSTAT_AUXV: - // FIXME: FreeBSD sticks an int at the beginning of the note - m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4); - break; - case FREEBSD::NT_PPC_VMX: - thread_data->vregset = note_data; - break; - default: - break; - } - } else if (note.n_name.substr(0, 11) == "NetBSD-CORE") { - // NetBSD per-thread information is stored in notes named - // "NetBSD-CORE@nnn" so match on the initial part of the string. - m_os = llvm::Triple::NetBSD; - if (note.n_type == NETBSD::NT_PROCINFO) { - ParseNetBSDProcInfo(*thread_data, note_data); - } else if (note.n_type == NETBSD::NT_AUXV) { - m_auxv = DataExtractor(note_data); - } else if (arch.GetMachine() == llvm::Triple::x86_64 && - note.n_type == NETBSD::NT_AMD64_REGS) { - thread_data->gpregset = note_data; - } else if (arch.GetMachine() == llvm::Triple::x86_64 && - note.n_type == NETBSD::NT_AMD64_FPREGS) { - thread_data->fpregset = note_data; - } - } else if (note.n_name.substr(0, 7) == "OpenBSD") { - // OpenBSD per-thread information is stored in notes named - // "OpenBSD@nnn" so match on the initial part of the string. - m_os = llvm::Triple::OpenBSD; - switch (note.n_type) { - case NT_OPENBSD_PROCINFO: - ParseOpenBSDProcInfo(*thread_data, note_data); - break; - case NT_OPENBSD_AUXV: - m_auxv = DataExtractor(note_data); - break; - case NT_OPENBSD_REGS: - thread_data->gpregset = note_data; - break; - case NT_OPENBSD_FPREGS: - thread_data->fpregset = note_data; - break; - } - } else if (note.n_name == "CORE") { - switch (note.n_type) { - case NT_PRSTATUS: - have_prstatus = true; - error = prstatus.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->prstatus_sig = prstatus.pr_cursig; - thread_data->tid = prstatus.pr_pid; - header_size = ELFLinuxPrStatus::GetSize(arch); - len = note_data.GetByteSize() - header_size; - thread_data->gpregset = DataExtractor(note_data, header_size, len); - break; - case NT_FPREGSET: - // In a i386 core file NT_FPREGSET is present, but it's not the result - // of the FXSAVE instruction like in 64 bit files. - // The result from FXSAVE is in NT_PRXFPREG for i386 core files - if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64) - thread_data->fpregset = note_data; - else if(arch.IsMIPS()) - thread_data->fpregset = note_data; - break; - case NT_PRPSINFO: - have_prpsinfo = true; - error = prpsinfo.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->name = prpsinfo.pr_fname; - SetID(prpsinfo.pr_pid); - break; - case NT_AUXV: - m_auxv = DataExtractor(note_data); - break; - case NT_FILE: { - m_nt_file_entries.clear(); - lldb::offset_t offset = 0; - const uint64_t count = note_data.GetAddress(&offset); - note_data.GetAddress(&offset); // Skip page size - for (uint64_t i = 0; i < count; ++i) { - NT_FILE_Entry entry; - entry.start = note_data.GetAddress(&offset); - entry.end = note_data.GetAddress(&offset); - entry.file_ofs = note_data.GetAddress(&offset); - m_nt_file_entries.push_back(entry); - } - for (uint64_t i = 0; i < count; ++i) { - const char *path = note_data.GetCStr(&offset); - if (path && path[0]) - m_nt_file_entries[i].path.SetCString(path); - } - } break; - case NT_SIGINFO: { - error = siginfo.Parse(note_data, arch); - if (error.Fail()) - return error; - thread_data->signo = siginfo.si_signo; - } break; - default: - break; + switch (note.info.n_type) { + case LINUX::NT_PRSTATUS: { + have_prstatus = true; + ELFLinuxPrStatus prstatus; + Status status = prstatus.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.prstatus_sig = prstatus.pr_cursig; + thread_data.tid = prstatus.pr_pid; + uint32_t header_size = ELFLinuxPrStatus::GetSize(arch); + size_t len = note.data.GetByteSize() - header_size; + thread_data.gpregset = DataExtractor(note.data, header_size, len); + break; + } + case LINUX::NT_PRPSINFO: { + have_prpsinfo = true; + ELFLinuxPrPsInfo prpsinfo; + Status status = prpsinfo.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.name = prpsinfo.pr_fname; + SetID(prpsinfo.pr_pid); + break; + } + case LINUX::NT_SIGINFO: { + ELFLinuxSigInfo siginfo; + Status status = siginfo.Parse(note.data, arch); + if (status.Fail()) + return status.ToError(); + thread_data.signo = siginfo.si_signo; + break; + } + case LINUX::NT_FILE: { + m_nt_file_entries.clear(); + lldb::offset_t offset = 0; + const uint64_t count = note.data.GetAddress(&offset); + note.data.GetAddress(&offset); // Skip page size + for (uint64_t i = 0; i < count; ++i) { + NT_FILE_Entry entry; + entry.start = note.data.GetAddress(&offset); + entry.end = note.data.GetAddress(&offset); + entry.file_ofs = note.data.GetAddress(&offset); + m_nt_file_entries.push_back(entry); } - } else if (note.n_name == "LINUX") { - switch (note.n_type) { - case NT_PRXFPREG: - thread_data->fpregset = note_data; + for (uint64_t i = 0; i < count; ++i) { + const char *path = note.data.GetCStr(&offset); + if (path && path[0]) + m_nt_file_entries[i].path.SetCString(path); } + break; + } + case LINUX::NT_AUXV: + m_auxv = note.data; + break; + default: + thread_data.notes.push_back(note); + break; } - - offset += note_size; } // Add last entry in the note section - if (thread_data && thread_data->gpregset.GetByteSize() > 0) { - m_thread_data.push_back(*thread_data); - } + if (have_prstatus) + m_thread_data.push_back(thread_data); + return llvm::Error::success(); +} - return error; +/// Parse Thread context from PT_NOTE segment and store it in the thread list +/// A note segment consists of one or more NOTE entries, but their types and +/// meaning differ depending on the OS. +llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment( + const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) { + assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE); + + auto notes_or_error = parseSegment(segment_data); + if(!notes_or_error) + return notes_or_error.takeError(); + switch (GetArchitecture().GetTriple().getOS()) { + case llvm::Triple::FreeBSD: + return parseFreeBSDNotes(*notes_or_error); + case llvm::Triple::Linux: + return parseLinuxNotes(*notes_or_error); + case llvm::Triple::NetBSD: + return parseNetBSDNotes(*notes_or_error); + case llvm::Triple::OpenBSD: + return parseOpenBSDNotes(*notes_or_error); + default: + return llvm::make_error<llvm::StringError>( + "Don't know how to parse core file. Unsupported OS.", + llvm::inconvertibleErrorCode()); + } } uint32_t ProcessElfCore::GetNumThreadContexts() { @@ -724,15 +743,18 @@ uint32_t ProcessElfCore::GetNumThreadContexts() { } ArchSpec ProcessElfCore::GetArchitecture() { - ObjectFileELF *core_file = - (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); ArchSpec arch; - core_file->GetArchitecture(arch); + m_core_module_sp->GetObjectFile()->GetArchitecture(arch); ArchSpec target_arch = GetTarget().GetArchitecture(); - - if (target_arch.IsMIPS()) + arch.MergeFrom(target_arch); + + // On MIPS there is no way to differentiate betwenn 32bit and 64bit core files + // and this information can't be merged in from the target arch so we fail + // back to unconditionally returning the target arch in this config. + if (target_arch.IsMIPS()) { return target_arch; + } return arch; } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index dbf7f926f855..325c0152e028 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -29,6 +29,7 @@ #include "lldb/Utility/Status.h" #include "Plugins/ObjectFile/ELF/ELFHeader.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" struct ThreadData; @@ -84,11 +85,21 @@ public: void RefreshStateAfterStop() override; + lldb_private::Status WillResume() override { + lldb_private::Status error; + error.SetErrorStringWithFormat( + "error: %s does not support resuming processes", + GetPluginName().GetCString()); + return error; + } + //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ bool IsAlive() override; + bool WarnBeforeDetach() const override { return false; } + //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ @@ -139,10 +150,8 @@ private: std::string m_dyld_plugin_name; DISALLOW_COPY_AND_ASSIGN(ProcessElfCore); - llvm::Triple::OSType m_os; - // True if m_thread_contexts contains valid entries - bool m_thread_data_valid; + bool m_thread_data_valid = false; // Contain thread data read from NOTE segments std::vector<ThreadData> m_thread_data; @@ -160,7 +169,7 @@ private: std::vector<NT_FILE_Entry> m_nt_file_entries; // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment - lldb_private::Status ParseThreadContextsFromNoteSegment( + llvm::Error ParseThreadContextsFromNoteSegment( const elf::ELFProgramHeader *segment_header, lldb_private::DataExtractor segment_data); @@ -170,6 +179,13 @@ private: // Parse a contiguous address range of the process from LOAD segment lldb::addr_t AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header); + + llvm::Expected<std::vector<lldb_private::CoreNote>> + parseSegment(const lldb_private::DataExtractor &segment); + llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); + llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes); }; #endif // liblldb_ProcessElfCore_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp index 81d88e69b97f..0d683153d9ed 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index e095eac5eaf8..a98d64caee17 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_arm_h_ #define liblldb_RegisterContextCorePOSIX_arm_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_arm() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 41c02bf94c37..919f8901d39a 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "RegisterContextPOSIXCore_arm64.h" - +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Target/Thread.h" @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm64(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index 3a2bbdb0a2eb..c519b1557189 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_arm64_h_ #define liblldb_RegisterContextCorePOSIX_arm64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_arm64() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index 7549cf074be7..e252b5a35e9c 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -16,12 +16,15 @@ using namespace lldb_private; RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_mips64(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index 2cb527a8de7c..cf1d8a5bc2d1 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_mips64_h_ #define liblldb_RegisterContextCorePOSIX_mips64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" @@ -24,7 +21,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_mips64() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index 62f6413722f7..8670e341a277 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -17,17 +17,21 @@ using namespace lldb_private; RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset, - const DataExtractor &vregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_powerpc(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + ArchSpec arch = register_info->GetTargetArchitecture(); + DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); m_fpr.SetByteOrder(fpregset.GetByteOrder()); + + DataExtractor vregset = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc); m_vec_buffer.reset( new DataBufferHeap(vregset.GetDataStart(), vregset.GetByteSize())); m_vec.SetData(m_vec_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index aaa95e5d2397..c352ab5912ff 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_ #define liblldb_RegisterContextCorePOSIX_powerpc_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_powerpc : public RegisterContextPOSIX_powerpc { @@ -23,8 +20,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset, - const lldb_private::DataExtractor &vregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_powerpc() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp new file mode 100644 index 000000000000..2237e72353ac --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp @@ -0,0 +1,132 @@ +//===-- RegisterContextPOSIXCore_ppc64le.cpp --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextPOSIXCore_ppc64le.h" + +#include "lldb/Core/RegisterValue.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" + +#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" + +using namespace lldb_private; + +RegisterContextCorePOSIX_ppc64le::RegisterContextCorePOSIX_ppc64le( + Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) + : RegisterContextPOSIX_ppc64le(thread, 0, register_info) { + m_gpr_buffer.reset( + new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + ArchSpec arch = register_info->GetTargetArchitecture(); + DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc); + m_fpr_buffer.reset( + new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); + + DataExtractor vmxregset = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc); + m_vmx_buffer.reset( + new DataBufferHeap(vmxregset.GetDataStart(), vmxregset.GetByteSize())); + m_vmx.SetData(m_vmx_buffer); + m_vmx.SetByteOrder(vmxregset.GetByteOrder()); + + DataExtractor vsxregset = getRegset(notes, arch.GetTriple(), PPC_VSX_Desc); + m_vsx_buffer.reset( + new DataBufferHeap(vsxregset.GetDataStart(), vsxregset.GetByteSize())); + m_vsx.SetData(m_vsx_buffer); + m_vsx.SetByteOrder(vsxregset.GetByteOrder()); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetFPRSize() const { + return k_num_fpr_registers_ppc64le * sizeof(uint64_t); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetVMXSize() const { + return (k_num_vmx_registers_ppc64le - 1) * sizeof(uint64_t) * 2 + + sizeof(uint32_t); +} + +size_t RegisterContextCorePOSIX_ppc64le::GetVSXSize() const { + return k_num_vsx_registers_ppc64le * sizeof(uint64_t) * 2; +} + +bool RegisterContextCorePOSIX_ppc64le::ReadRegister( + const RegisterInfo *reg_info, RegisterValue &value) { + lldb::offset_t offset = reg_info->byte_offset; + + if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint64_t v; + offset -= GetGPRSize(); + offset = m_fpr.CopyData(offset, reg_info->byte_size, &v); + + if (offset == reg_info->byte_size) { + value.SetBytes(&v, reg_info->byte_size, m_fpr.GetByteOrder()); + return true; + } + } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + offset -= GetGPRSize() + GetFPRSize(); + offset = m_vmx.CopyData(offset, reg_info->byte_size, &v); + + if (offset == reg_info->byte_size) { + value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder()); + return true; + } + } else if (IsVSX(reg_info->kinds[lldb::eRegisterKindLLDB])) { + uint32_t v[4]; + lldb::offset_t tmp_offset; + offset -= GetGPRSize() + GetFPRSize() + GetVMXSize(); + + if (offset < GetVSXSize() / 2) { + tmp_offset = m_vsx.CopyData(offset / 2, reg_info->byte_size / 2, &v); + + if (tmp_offset != reg_info->byte_size / 2) { + return false; + } + + uint8_t *dst = (uint8_t *)&v + sizeof(uint64_t); + tmp_offset = m_fpr.CopyData(offset / 2, reg_info->byte_size / 2, dst); + + if (tmp_offset != reg_info->byte_size / 2) { + return false; + } + + value.SetBytes(&v, reg_info->byte_size, m_vsx.GetByteOrder()); + return true; + } else { + offset = + m_vmx.CopyData(offset - GetVSXSize() / 2, reg_info->byte_size, &v); + if (offset == reg_info->byte_size) { + value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder()); + return true; + } + } + } else { + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + + if (offset == reg_info->byte_offset + reg_info->byte_size) { + if (reg_info->byte_size < sizeof(v)) + value = (uint32_t)v; + else + value = v; + return true; + } + } + + return false; +} + +bool RegisterContextCorePOSIX_ppc64le::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue &value) { + return false; +} diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h new file mode 100644 index 000000000000..c860781d60be --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.h @@ -0,0 +1,49 @@ +//===-- RegisterContextPOSIXCore_ppc64le.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_RegisterContextCorePOSIX_ppc64le_h_ +#define liblldb_RegisterContextCorePOSIX_ppc64le_h_ + +#include "Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" +#include "lldb/Utility/DataExtractor.h" + +class RegisterContextCorePOSIX_ppc64le : public RegisterContextPOSIX_ppc64le { +public: + RegisterContextCorePOSIX_ppc64le( + lldb_private::Thread &thread, + lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + llvm::ArrayRef<lldb_private::CoreNote> notes); + + bool ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value) override; + + bool WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) override; + +protected: + size_t GetFPRSize() const; + + size_t GetVMXSize() const; + + size_t GetVSXSize() const; + +private: + lldb::DataBufferSP m_gpr_buffer; + lldb::DataBufferSP m_fpr_buffer; + lldb::DataBufferSP m_vmx_buffer; + lldb::DataBufferSP m_vsx_buffer; + lldb_private::DataExtractor m_gpr; + lldb_private::DataExtractor m_fpr; + lldb_private::DataExtractor m_vmx; + lldb_private::DataExtractor m_vsx; +}; + +#endif // liblldb_RegisterContextCorePOSIX_ppc64le_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index b3530a8d6a42..f0edbf1ea854 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -17,13 +17,15 @@ using namespace lldb_private; RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_s390x(thread, 0, register_info) { m_gpr_buffer.reset( new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); m_gpr.SetData(m_gpr_buffer); m_gpr.SetByteOrder(gpregset.GetByteOrder()); + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); m_fpr_buffer.reset( new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); m_fpr.SetData(m_fpr_buffer); diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h index 2b4ae10a87bd..0df136372bdd 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_s390x_h_ #define liblldb_RegisterContextCorePOSIX_s390x_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Utility/DataExtractor.h" class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x { @@ -23,7 +20,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_s390x() override; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 5766923186d1..a5c7ffda1da5 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -16,7 +16,7 @@ using namespace lldb_private; RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64( Thread &thread, RegisterInfoInterface *register_info, - const DataExtractor &gpregset, const DataExtractor &fpregset) + const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_x86(thread, 0, register_info) { size_t size, len; @@ -27,6 +27,8 @@ RegisterContextCorePOSIX_x86_64::RegisterContextCorePOSIX_x86_64( if (len != size) m_gpregset.reset(); + DataExtractor fpregset = getRegset( + notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); size = sizeof(FXSAVE); m_fpregset.reset(new uint8_t[size]); len = diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h index 8340368f8c3c..509624174a89 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -10,11 +10,8 @@ #ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_ #define liblldb_RegisterContextCorePOSIX_x86_64_h_ -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h" +#include "Plugins/Process/elf-core/RegisterUtilities.h" class RegisterContextCorePOSIX_x86_64 : public RegisterContextPOSIX_x86 { public: @@ -22,7 +19,7 @@ public: lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, const lldb_private::DataExtractor &gpregset, - const lldb_private::DataExtractor &fpregset); + llvm::ArrayRef<lldb_private::CoreNote> notes); bool ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override; diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.cpp b/source/Plugins/Process/elf-core/RegisterUtilities.cpp new file mode 100644 index 000000000000..3837abadd0f6 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterUtilities.cpp @@ -0,0 +1,39 @@ +//===-- RegisterUtilities.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/elf-core/RegisterUtilities.h" +#include "llvm/ADT/STLExtras.h" + +using namespace lldb_private; + +static llvm::Optional<uint32_t> +getNoteType(const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs) { + for (const auto &Entry : RegsetDescs) { + if (Entry.OS != Triple.getOS()) + continue; + if (Entry.Arch != llvm::Triple::UnknownArch && + Entry.Arch != Triple.getArch()) + continue; + return Entry.Note; + } + return llvm::None; +} + +DataExtractor lldb_private::getRegset(llvm::ArrayRef<CoreNote> Notes, + const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs) { + auto TypeOr = getNoteType(Triple, RegsetDescs); + if (!TypeOr) + return DataExtractor(); + uint32_t Type = *TypeOr; + auto Iter = llvm::find_if( + Notes, [Type](const CoreNote &Note) { return Note.info.n_type == Type; }); + return Iter == Notes.end() ? DataExtractor() : Iter->data; +} diff --git a/source/Plugins/Process/elf-core/RegisterUtilities.h b/source/Plugins/Process/elf-core/RegisterUtilities.h new file mode 100644 index 000000000000..9170d94c04b6 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -0,0 +1,110 @@ +//===-- RegisterUtilities.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_REGISTERUTILITIES_H +#define LLDB_REGISTERUTILITIES_H + +#include "Plugins/ObjectFile/ELF/ObjectFileELF.h" +#include "lldb/Utility/DataExtractor.h" + +namespace lldb_private { +/// Core files PT_NOTE segment descriptor types + +namespace FREEBSD { +enum { + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_THRMISC = 7, + NT_PROCSTAT_AUXV = 16, + NT_PPC_VMX = 0x100 +}; +} + +namespace NETBSD { +enum { NT_PROCINFO = 1, NT_AUXV, NT_AMD64_REGS = 33, NT_AMD64_FPREGS = 35 }; +} + +namespace OPENBSD { +enum { + NT_PROCINFO = 10, + NT_AUXV = 11, + NT_REGS = 20, + NT_FPREGS = 21, +}; +} + +namespace LINUX { +enum { + NT_PRSTATUS = 1, + NT_FPREGSET, + NT_PRPSINFO, + NT_TASKSTRUCT, + NT_PLATFORM, + NT_AUXV, + NT_FILE = 0x46494c45, + NT_SIGINFO = 0x53494749, + NT_PPC_VMX = 0x100, + NT_PPC_VSX = 0x102, + NT_PRXFPREG = 0x46e62b7f, +}; +} + +struct CoreNote { + ELFNote info; + DataExtractor data; +}; + +// A structure describing how to find a register set in a core file from a given +// OS. +struct RegsetDesc { + // OS to which this entry applies to. Must not be UnknownOS. + llvm::Triple::OSType OS; + + // Architecture to which this entry applies to. Can be UnknownArch, in which + // case it applies to all architectures of a given OS. + llvm::Triple::ArchType Arch; + + // The note type under which the register set can be found. + uint32_t Note; +}; + +// Returns the register set in Notes which corresponds to the specified Triple +// according to the list of register set descriptions in RegsetDescs. The list +// is scanned linearly, so you can use a more specific entry (e.g. linux-i386) +// to override a more general entry (e.g. general linux), as long as you place +// it earlier in the list. If a register set is not found, it returns an empty +// DataExtractor. +DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes, + const llvm::Triple &Triple, + llvm::ArrayRef<RegsetDesc> RegsetDescs); + +constexpr RegsetDesc FPR_Desc[] = { + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_FPREGSET}, + // In a i386 core file NT_FPREGSET is present, but it's not the result + // of the FXSAVE instruction like in 64 bit files. + // The result from FXSAVE is in NT_PRXFPREG for i386 core files + {llvm::Triple::Linux, llvm::Triple::x86, LINUX::NT_PRXFPREG}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_FPREGSET}, + {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::NT_AMD64_FPREGS}, + {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, +}; + +constexpr RegsetDesc PPC_VMX_Desc[] = { + {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, FREEBSD::NT_PPC_VMX}, + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VMX}, +}; + +constexpr RegsetDesc PPC_VSX_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::UnknownArch, LINUX::NT_PPC_VSX}, +}; + +} // namespace lldb_private + +#endif // #ifndef LLDB_REGISTERUTILITIES_H diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 096c20363c78..10c1ed288b2c 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -18,9 +18,9 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" +#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" @@ -28,11 +28,13 @@ #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h" #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h" #include "ProcessElfCore.h" #include "RegisterContextPOSIXCore_arm.h" #include "RegisterContextPOSIXCore_arm64.h" #include "RegisterContextPOSIXCore_mips64.h" #include "RegisterContextPOSIXCore_powerpc.h" +#include "RegisterContextPOSIXCore_ppc64le.h" #include "RegisterContextPOSIXCore_s390x.h" #include "RegisterContextPOSIXCore_x86_64.h" #include "ThreadElfCore.h" @@ -45,8 +47,7 @@ using namespace lldb_private; //---------------------------------------------------------------------- ThreadElfCore::ThreadElfCore(Process &process, const ThreadData &td) : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(), - m_signo(td.signo), m_gpregset_data(td.gpregset), - m_fpregset_data(td.fpregset), m_vregset_data(td.vregset) {} + m_signo(td.signo), m_gpregset_data(td.gpregset), m_notes(td.notes) {} ThreadElfCore::~ThreadElfCore() { DestroyThread(); } @@ -142,6 +143,9 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { case llvm::Triple::mips64: reg_interface = new RegisterContextLinux_mips64(arch); break; + case llvm::Triple::ppc64le: + reg_interface = new RegisterInfoPOSIX_ppc64le(arch); + break; case llvm::Triple::systemz: reg_interface = new RegisterContextLinux_s390x(arch); break; @@ -191,36 +195,39 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::arm: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_arm( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::mipsel: case llvm::Triple::mips: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::mips64: case llvm::Triple::mips64el: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::ppc: case llvm::Triple::ppc64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc( - *this, reg_interface, m_gpregset_data, m_fpregset_data, - m_vregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); + break; + case llvm::Triple::ppc64le: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_ppc64le( + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::systemz: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; case llvm::Triple::x86: case llvm::Triple::x86_64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64( - *this, reg_interface, m_gpregset_data, m_fpregset_data)); + *this, reg_interface, m_gpregset_data, m_notes)); break; default: break; @@ -249,7 +256,7 @@ ELFLinuxPrStatus::ELFLinuxPrStatus() { memset(this, 0, sizeof(ELFLinuxPrStatus)); } -size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { +size_t ELFLinuxPrStatus::GetSize(const lldb_private::ArchSpec &arch) { constexpr size_t mips_linux_pr_status_size_o32 = 96; constexpr size_t mips_linux_pr_status_size_n32 = 72; if (arch.IsMIPS()) { @@ -265,6 +272,7 @@ size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { switch (arch.GetCore()) { case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: + case lldb_private::ArchSpec::eCore_ppc64le_generic: return sizeof(ELFLinuxPrStatus); case lldb_private::ArchSpec::eCore_x86_32_i386: case lldb_private::ArchSpec::eCore_x86_32_i486: @@ -274,7 +282,8 @@ size_t ELFLinuxPrStatus::GetSize(lldb_private::ArchSpec &arch) { } } -Status ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) { +Status ELFLinuxPrStatus::Parse(const DataExtractor &data, + const ArchSpec &arch) { Status error; if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat( @@ -323,7 +332,7 @@ ELFLinuxPrPsInfo::ELFLinuxPrPsInfo() { memset(this, 0, sizeof(ELFLinuxPrPsInfo)); } -size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) { +size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) { constexpr size_t mips_linux_pr_psinfo_size_o32_n32 = 128; if (arch.IsMIPS()) { uint8_t address_byte_size = arch.GetAddressByteSize(); @@ -344,7 +353,8 @@ size_t ELFLinuxPrPsInfo::GetSize(lldb_private::ArchSpec &arch) { } } -Status ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { +Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data, + const ArchSpec &arch) { Status error; ByteOrder byteorder = data.GetByteOrder(); if (GetSize(arch) > data.GetByteSize()) { @@ -413,7 +423,7 @@ size_t ELFLinuxSigInfo::GetSize(const lldb_private::ArchSpec &arch) { } } -Status ELFLinuxSigInfo::Parse(DataExtractor &data, const ArchSpec &arch) { +Status ELFLinuxSigInfo::Parse(const DataExtractor &data, const ArchSpec &arch) { Status error; if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat( diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index 521875413715..335f698dbb24 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -10,14 +10,11 @@ #ifndef liblldb_ThreadElfCore_h_ #define liblldb_ThreadElfCore_h_ -// C Includes -// C++ Includes -#include <string> - -// Other libraries and framework includes -// Project includes +#include "Plugins/Process/elf-core/RegisterUtilities.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/DataExtractor.h" +#include "llvm/ADT/DenseMap.h" +#include <string> struct compat_timeval { alignas(8) uint64_t tv_sec; @@ -57,15 +54,15 @@ struct ELFLinuxPrStatus { ELFLinuxPrStatus(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, - lldb_private::ArchSpec &arch); + lldb_private::Status Parse(const lldb_private::DataExtractor &data, + const lldb_private::ArchSpec &arch); // Return the bytesize of the structure // 64 bit - just sizeof // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch); + static size_t GetSize(const lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrStatus) == 112, @@ -78,7 +75,7 @@ struct ELFLinuxSigInfo { ELFLinuxSigInfo(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, + lldb_private::Status Parse(const lldb_private::DataExtractor &data, const lldb_private::ArchSpec &arch); // Return the bytesize of the structure @@ -113,15 +110,15 @@ struct ELFLinuxPrPsInfo { ELFLinuxPrPsInfo(); - lldb_private::Status Parse(lldb_private::DataExtractor &data, - lldb_private::ArchSpec &arch); + lldb_private::Status Parse(const lldb_private::DataExtractor &data, + const lldb_private::ArchSpec &arch); // Return the bytesize of the structure // 64 bit - just sizeof // 32 bit - hardcoded because we are reusing the struct, but some of the // members are smaller - // so the layout is not the same - static size_t GetSize(lldb_private::ArchSpec &arch); + static size_t GetSize(const lldb_private::ArchSpec &arch); }; static_assert(sizeof(ELFLinuxPrPsInfo) == 136, @@ -129,8 +126,7 @@ static_assert(sizeof(ELFLinuxPrPsInfo) == 136, struct ThreadData { lldb_private::DataExtractor gpregset; - lldb_private::DataExtractor fpregset; - lldb_private::DataExtractor vregset; + std::vector<lldb_private::CoreNote> notes; lldb::tid_t tid; int signo = 0; int prstatus_sig = 0; @@ -177,8 +173,7 @@ protected: int m_signo; lldb_private::DataExtractor m_gpregset_data; - lldb_private::DataExtractor m_fpregset_data; - lldb_private::DataExtractor m_vregset_data; + std::vector<lldb_private::CoreNote> m_notes; bool CalculateStopInfo() override; }; diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt index 5e51feef1d3f..7ae25f83c5f8 100644 --- a/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -7,6 +7,10 @@ set(LLDB_PLUGINS lldbPluginPlatformMacOSX ) +if(HAVE_LIBCOMPRESSION) + set(LIBCOMPRESSION compression) +endif() + add_lldb_library(lldbPluginProcessGDBRemote PLUGIN GDBRemoteClientBase.cpp GDBRemoteCommunication.cpp @@ -30,6 +34,7 @@ add_lldb_library(lldbPluginProcessGDBRemote PLUGIN lldbTarget lldbUtility ${LLDB_PLUGINS} + ${LIBCOMPRESSION} LINK_COMPONENTS Support ) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 0c4df7e3f306..949cf19db658 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -600,10 +600,9 @@ bool GDBRemoteCommunication::DecompressPacket() { #if defined(HAVE_LIBCOMPRESSION) // libcompression is weak linked so check that compression_decode_buffer() is // available - if (compression_decode_buffer != NULL && - (m_compression_type == CompressionType::ZlibDeflate || - m_compression_type == CompressionType::LZFSE || - m_compression_type == CompressionType::LZ4)) { + if (m_compression_type == CompressionType::ZlibDeflate || + m_compression_type == CompressionType::LZFSE || + m_compression_type == CompressionType::LZ4) { compression_algorithm compression_type; if (m_compression_type == CompressionType::LZFSE) compression_type = COMPRESSION_LZFSE; @@ -815,7 +814,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len, // checksum if (m_bytes[0] == '$' && total_length > 4) { for (size_t i = 0; !binary && i < total_length; ++i) { - if (isprint(m_bytes[i]) == 0 && isspace(m_bytes[i]) == 0) { + unsigned char c = m_bytes[i]; + if (isprint(c) == 0 && isspace(c) == 0) { binary = true; } } @@ -1375,3 +1375,39 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes, } } } + +void llvm::format_provider<GDBRemoteCommunication::PacketResult>::format( + const GDBRemoteCommunication::PacketResult &result, raw_ostream &Stream, + StringRef Style) { + using PacketResult = GDBRemoteCommunication::PacketResult; + + switch (result) { + case PacketResult::Success: + Stream << "Success"; + break; + case PacketResult::ErrorSendFailed: + Stream << "ErrorSendFailed"; + break; + case PacketResult::ErrorSendAck: + Stream << "ErrorSendAck"; + break; + case PacketResult::ErrorReplyFailed: + Stream << "ErrorReplyFailed"; + break; + case PacketResult::ErrorReplyTimeout: + Stream << "ErrorReplyTimeout"; + break; + case PacketResult::ErrorReplyInvalid: + Stream << "ErrorReplyInvalid"; + break; + case PacketResult::ErrorReplyAck: + Stream << "ErrorReplyAck"; + break; + case PacketResult::ErrorDisconnected: + Stream << "ErrorDisconnected"; + break; + case PacketResult::ErrorNoSequenceLock: + Stream << "ErrorNoSequenceLock"; + break; + } +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index ce90de3e8470..ecc9386e49c7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -290,4 +290,14 @@ private: } // namespace process_gdb_remote } // namespace lldb_private +namespace llvm { +template <> +struct format_provider< + lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> { + static void format(const lldb_private::process_gdb_remote:: + GDBRemoteCommunication::PacketResult &state, + raw_ostream &Stream, StringRef Style); +}; +} // namespace llvm + #endif // liblldb_GDBRemoteCommunication_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index e6fd386b903b..867f57c475ce 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1022,10 +1022,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( std::string avail_name; #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzfse") { avail_type = CompressionType::LZFSE; @@ -1037,10 +1034,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "zlib-deflate") { avail_type = CompressionType::ZlibDeflate; @@ -1064,10 +1058,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lz4") { avail_type = CompressionType::LZ4; @@ -1079,10 +1070,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( #endif #if defined(HAVE_LIBCOMPRESSION) - // libcompression is weak linked so test if compression_decode_buffer() is - // available - if (compression_decode_buffer != NULL && - avail_type == CompressionType::None) { + if (avail_type == CompressionType::None) { for (auto compression : supported_compressions) { if (compression == "lzma") { avail_type = CompressionType::LZMA; @@ -1601,21 +1589,24 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction( // and we only want to override this behavior if we have explicitly // received a qHostInfo telling us otherwise if (m_qHostInfo_is_valid != eLazyBoolYes) { - // On targets like MIPS, watchpoint exceptions are always generated - // before the instruction is executed. The connected target may not - // support qHostInfo or qWatchpointSupportInfo packets. + // On targets like MIPS and ppc64le, watchpoint exceptions are always + // generated before the instruction is executed. The connected target + // may not support qHostInfo or qWatchpointSupportInfo packets. if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el) + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el || + atype == llvm::Triple::ppc64le) after = false; else after = true; } else { - // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo - // if it is not calculated before. - if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && - (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || - atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) + // For MIPS and ppc64le, set m_watchpoints_trigger_after_instruction to + // eLazyBoolNo if it is not calculated before. + if ((m_watchpoints_trigger_after_instruction == eLazyBoolCalculate && + (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel || + atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)) || + atype == llvm::Triple::ppc64le) { m_watchpoints_trigger_after_instruction = eLazyBoolNo; + } after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo); } @@ -2624,8 +2615,8 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( * tid. * Assume pid=tid=1 in such cases. */ - if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && - IsConnected()) { + if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) && + thread_ids.size() == 0 && IsConnected()) { thread_ids.push_back(1); } } else { @@ -3451,7 +3442,9 @@ ParseModuleSpec(StructuredData::Dictionary *dict) { if (!dict->GetValueForKeyAsString("uuid", string)) return llvm::None; - result.GetUUID().SetFromStringRef(string, string.size()); + if (result.GetUUID().SetFromStringRef(string, string.size() / 2) != + string.size()) + return llvm::None; if (!dict->GetValueForKeyAsInteger("file_offset", integer)) return llvm::None; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 712d85eed082..ba67b8246398 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -20,10 +20,8 @@ #include <string> #include <vector> -// Other libraries and framework includes -// Project includes -#include "lldb/Core/ArchSpec.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/StreamGDBRemote.h" #include "lldb/Utility/StructuredData.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index f53db502be93..3cf6b8ac07b2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -403,8 +403,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo( match_info.SetMatchAllUsers( Args::StringToBoolean(value, false, &success)); } else if (key.equals("triple")) { - match_info.GetProcessInfo().GetArchitecture().SetTriple( - value.str().c_str(), NULL); + match_info.GetProcessInfo().GetArchitecture() = + HostInfo::GetAugmentedArchSpec(value); } else { success = false; } @@ -973,8 +973,7 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch( const uint32_t bytes_left = packet.GetBytesLeft(); if (bytes_left > 0) { const char *arch_triple = packet.Peek(); - ArchSpec arch_spec(arch_triple, NULL); - m_process_launch_info.SetArchitecture(arch_spec); + m_process_launch_info.SetArchitecture(HostInfo::GetAugmentedArchSpec(arch_triple)); return SendOKResponse(); } return SendErrorResponse(13); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 9294359dbef1..32741c2404e2 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -204,21 +204,8 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { }); } -Status -GDBRemoteCommunicationServerLLGS::SetLaunchArguments(const char *const args[], - int argc) { - if ((argc < 1) || !args || !args[0] || !args[0][0]) - return Status("%s: no process command line specified to launch", - __FUNCTION__); - - m_process_launch_info.SetArguments(const_cast<const char **>(args), true); - return Status(); -} - -Status -GDBRemoteCommunicationServerLLGS::SetLaunchFlags(unsigned int launch_flags) { - m_process_launch_info.GetFlags().Set(launch_flags); - return Status(); +void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { + m_process_launch_info = info; } Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { @@ -244,13 +231,8 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { "process but one already exists"); auto process_or = m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); - if (!process_or) { - Status status(process_or.takeError()); - llvm::errs() << llvm::formatv( - "failed to launch executable `{0}`: {1}", - m_process_launch_info.GetArguments().GetArgumentAtIndex(0), status); - return status; - } + if (!process_or) + return Status(process_or.takeError()); m_debugged_process_up = std::move(*process_or); } @@ -396,12 +378,12 @@ static void AppendHexValue(StreamString &response, const uint8_t *buf, } static void WriteRegisterValueInHexFixedWidth( - StreamString &response, NativeRegisterContextSP ®_ctx_sp, + StreamString &response, NativeRegisterContext ®_ctx, const RegisterInfo ®_info, const RegisterValue *reg_value_p, lldb::ByteOrder byte_order) { RegisterValue reg_value; if (!reg_value_p) { - Status error = reg_ctx_sp->ReadRegister(®_info, reg_value); + Status error = reg_ctx.ReadRegister(®_info, reg_value); if (error.Success()) reg_value_p = ®_value; // else log. @@ -423,9 +405,7 @@ static void WriteRegisterValueInHexFixedWidth( static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); - if (!reg_ctx_sp) - return nullptr; + NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); @@ -448,14 +428,14 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { for (const uint32_t *generic_reg_p = k_expedited_registers; *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) { - uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + uint32_t reg_num = reg_ctx.ConvertRegisterKindToRegisterNumber( eRegisterKindGeneric, *generic_reg_p); if (reg_num == LLDB_INVALID_REGNUM) continue; // Target does not support the given register. #endif const RegisterInfo *const reg_info_p = - reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); + reg_ctx.GetRegisterInfoAtIndex(reg_num); if (reg_info_p == nullptr) { if (log) log->Printf( @@ -469,7 +449,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { // registers. RegisterValue reg_value; - Status error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); + Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); if (error.Fail()) { if (log) log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", @@ -480,7 +460,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { } StreamString stream; - WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, + WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, ®_value, lldb::eByteOrderBig); register_object_sp->SetObject( @@ -523,16 +503,16 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, // Ensure we can get info on the given thread. uint32_t thread_idx = 0; - for (NativeThreadProtocolSP thread_sp; - (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; + for (NativeThreadProtocol *thread; + (thread = process.GetThreadAtIndex(thread_idx)) != nullptr; ++thread_idx) { - lldb::tid_t tid = thread_sp->GetID(); + lldb::tid_t tid = thread->GetID(); // Grab the reason this thread stopped. struct ThreadStopInfo tid_stop_info; std::string description; - if (!thread_sp->GetStopReason(tid_stop_info, description)) + if (!thread->GetStopReason(tid_stop_info, description)) return nullptr; const int signum = tid_stop_info.details.signal.signo; @@ -548,7 +528,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, threads_array_sp->AppendObject(thread_obj_sp); if (!abridged) { - if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp)) + if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) thread_obj_sp->SetObject("registers", registers_sp); } @@ -556,7 +536,7 @@ static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, if (signum != 0) thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); - const std::string thread_name = thread_sp->GetName(); + const std::string thread_name = thread->GetName(); if (!thread_name.empty()) thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); @@ -604,14 +584,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( m_debugged_process_up->GetID(), tid); // Ensure we can get info on the given thread. - NativeThreadProtocolSP thread_sp(m_debugged_process_up->GetThreadByID(tid)); - if (!thread_sp) + NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + if (!thread) return Send |