diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins')
301 files changed, 8423 insertions, 4766 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp index d36aeca21c69..505c7d416a82 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.cpp @@ -13,6 +13,7 @@ #include "ABISysV_arm64.h" #include "Utility/ARM64_DWARF_Registers.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Target/Process.h" LLDB_PLUGIN_DEFINE(ABIAArch64) @@ -30,6 +31,18 @@ void ABIAArch64::Terminate() { #endif // LLDB_ENABLE_ALL } +lldb::addr_t ABIAArch64::FixCodeAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) + return FixAddress(pc, process_sp->GetCodeAddressMask()); + return pc; +} + +lldb::addr_t ABIAArch64::FixDataAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) + return FixAddress(pc, process_sp->GetDataAddressMask()); + return pc; +} + std::pair<uint32_t, uint32_t> ABIAArch64::GetEHAndDWARFNums(llvm::StringRef name) { if (name == "pc") diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h index bdff648f1b52..41bbf5cfdeb9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIAArch64.h @@ -16,7 +16,14 @@ public: static void Initialize(); static void Terminate(); + virtual lldb::addr_t FixCodeAddress(lldb::addr_t pc) override; + virtual lldb::addr_t FixDataAddress(lldb::addr_t pc) override; + protected: + virtual lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) { + return pc; + } + std::pair<uint32_t, uint32_t> GetEHAndDWARFNums(llvm::StringRef name) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp index 09b319a84a08..348a081cfe17 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp @@ -66,7 +66,7 @@ bool ABIMacOSX_arm64::PrepareTrivialCall( if (log) { StreamString s; - s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64 + s.Printf("ABIMacOSX_arm64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64, thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, @@ -86,7 +86,7 @@ bool ABIMacOSX_arm64::PrepareTrivialCall( eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); // x0 - x7 contain first 8 simple args - if (args.size() > 8) // TODO handle more than 6 arguments + if (args.size() > 8) // TODO handle more than 8 arguments return false; for (size_t i = 0; i < args.size(); ++i) { @@ -384,6 +384,7 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); @@ -654,7 +655,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) { @@ -814,6 +815,11 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl( return return_valobj_sp; } +lldb::addr_t ABIMacOSX_arm64::FixAddress(addr_t pc, addr_t mask) { + lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; + return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); +} + void ABIMacOSX_arm64::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc, CreateInstance); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h index fc8ccee92e71..dc3ab35115fd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h @@ -62,6 +62,8 @@ public: return true; } + lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override; + // Static Functions static void Initialize(); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp index 1214195dcfc0..16fb38e107c3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -356,6 +356,7 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); @@ -622,7 +623,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) { @@ -781,6 +782,61 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl( return return_valobj_sp; } +lldb::addr_t ABISysV_arm64::FixAddress(addr_t pc, addr_t mask) { + lldb::addr_t pac_sign_extension = 0x0080000000000000ULL; + return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); +} + +// Reads code or data address mask for the current Linux process. +static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp, + llvm::StringRef reg_name) { + // Linux configures user-space virtual addresses with top byte ignored. + // We set default value of mask such that top byte is masked out. + uint64_t address_mask = ~((1ULL << 56) - 1); + // If Pointer Authentication feature is enabled then Linux exposes + // PAC data and code mask register. Try reading relevant register + // below and merge it with default address mask calculated above. + lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); + if (thread_sp) { + lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (reg_ctx_sp) { + const RegisterInfo *reg_info = + reg_ctx_sp->GetRegisterInfoByName(reg_name, 0); + if (reg_info) { + lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned( + reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS); + if (mask_reg_val != LLDB_INVALID_ADDRESS) + address_mask |= mask_reg_val; + } + } + } + return address_mask; +} + +lldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) { + if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && + !process_sp->GetCodeAddressMask()) + process_sp->SetCodeAddressMask( + ReadLinuxProcessAddressMask(process_sp, "code_mask")); + + return FixAddress(pc, process_sp->GetCodeAddressMask()); + } + return pc; +} + +lldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) { + if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && + !process_sp->GetDataAddressMask()) + process_sp->SetDataAddressMask( + ReadLinuxProcessAddressMask(process_sp, "data_mask")); + + return FixAddress(pc, process_sp->GetDataAddressMask()); + } + return pc; +} + void ABISysV_arm64::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), "SysV ABI for AArch64 targets", CreateInstance); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h index aeb74acc38b5..3428a7ad9418 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h @@ -67,6 +67,8 @@ public: bool GetPointerReturnRegister(const char *&name) override; + lldb::addr_t FixAddress(lldb::addr_t pc, lldb::addr_t mask) override; + // Static Functions static void Initialize(); @@ -83,6 +85,9 @@ public: uint32_t GetPluginVersion() override; + lldb::addr_t FixCodeAddress(lldb::addr_t pc) override; + lldb::addr_t FixDataAddress(lldb::addr_t pc) override; + protected: lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp index be8586722d8f..60cdbc534113 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARC/ABISysV_arc.cpp @@ -466,7 +466,7 @@ ABISysV_arc::GetReturnValueObjectSimple(Thread &thread, if (!SetSizedInteger(value.GetScalar(), raw_value, byte_size, is_signed)) return ValueObjectSP(); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); } // Pointer return type. else if (type_flags & eTypeIsPointer) { @@ -474,7 +474,7 @@ ABISysV_arc::GetReturnValueObjectSimple(Thread &thread, LLDB_REGNUM_GENERIC_ARG1); value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); } // Floating point return type. else if (type_flags & eTypeIsFloat) { @@ -537,7 +537,7 @@ ValueObjectSP ABISysV_arc::GetReturnValueObjectImpl(Thread &thread, auto reg_info_r0 = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); value.GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_r0, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); } // Floating point return type. else if (retType.isFloatingPointTy()) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp index 06c4590b7740..e429f3ee0cc4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABIMacOSX_arm.cpp @@ -1824,6 +1824,7 @@ bool ABIMacOSX_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp index 26b3152bed16..3e544e0483a7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp @@ -1617,7 +1617,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; - } else if (compiler_type.IsVectorType(nullptr, nullptr)) { + } else if (compiler_type.IsVectorType()) { if (IsArmHardFloat(thread) && (*byte_size == 8 || *byte_size == 16)) { is_vfp_candidate = true; vfp_byte_size = 8; @@ -1704,7 +1704,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( if (homogeneous_count > 0 && homogeneous_count <= 4) { llvm::Optional<uint64_t> base_byte_size = base_type.GetByteSize(&thread); - if (base_type.IsVectorType(nullptr, nullptr)) { + if (base_type.IsVectorType()) { if (base_byte_size && (*base_byte_size == 8 || *base_byte_size == 16)) { is_vfp_candidate = true; @@ -1940,6 +1940,7 @@ bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp index 47aaefd3b228..6794f7d07210 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp @@ -1225,6 +1225,7 @@ bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp index d66e0926ad99..538ec06c3b0d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp @@ -985,6 +985,7 @@ bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp index 751555722dac..7220508c75ff 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips64.cpp @@ -764,7 +764,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl( const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) { @@ -1156,6 +1156,7 @@ bool ABISysV_mips64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp index 91d2e59ed632..98a14b50cbf3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc.cpp @@ -520,7 +520,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger) { @@ -603,7 +603,7 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple( reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { @@ -683,8 +683,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl( r3_value.GetData(r3_data); rdx_value.GetData(rdx_data); - uint32_t fp_bytes = - 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far @@ -751,7 +749,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl( break; } else if (*field_bit_width == 64) { copy_from_offset = 0; - fp_bytes += field_byte_width; } else if (*field_bit_width == 32) { // This one is kind of complicated. If we are in an "eightbyte" // with another float, we'll be stuffed into an xmm register with @@ -815,8 +812,6 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl( copy_from_offset = integer_bytes - 8; integer_bytes += field_byte_width; } - } else { - fp_bytes += field_byte_width; } } } @@ -900,6 +895,7 @@ bool ABISysV_ppc::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 4; + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp index c7cb7736df9f..7cc9482e7c5d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/PowerPC/ABISysV_ppc64.cpp @@ -577,7 +577,7 @@ private: ValueSP NewScalarValue(CompilerType &type) { ValueSP value_sp(new Value); value_sp->SetCompilerType(type); - value_sp->SetValueType(Value::eValueTypeScalar); + value_sp->SetValueType(Value::ValueType::Scalar); return value_sp; } @@ -1003,6 +1003,7 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 8; + row->SetUnspecifiedRegistersAreUndefined(true); row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp index 22a64170017b..88e85111d871 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/SystemZ/ABISysV_s390x.cpp @@ -487,7 +487,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple( const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger) { @@ -571,7 +571,7 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple( reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp index 89112deb2c4a..461e4af599d3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIMacOSX_i386.cpp @@ -389,6 +389,7 @@ bool ABIMacOSX_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp index 2f47d3f462d2..7d2f0a64d679 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_i386.cpp @@ -378,14 +378,14 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); value.GetScalar() = ptr; return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); llvm::Optional<uint64_t> byte_size = return_compiler_type.GetByteSize(&thread); if (!byte_size) @@ -453,7 +453,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple( uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); value.GetScalar() = enm; return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); @@ -652,6 +652,7 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp index 2aa2c02b2e87..196b45b3b6da 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -399,7 +399,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger) { @@ -487,7 +487,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple( value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { @@ -887,6 +887,7 @@ bool ABISysV_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { const int32_t ptr_size = 8; row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp index 06e0ce40836d..6c473c652c5f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -408,7 +408,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); bool success = false; if (type_flags & eTypeIsInteger) { @@ -494,7 +494,7 @@ ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple( value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0); - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { @@ -767,6 +767,7 @@ bool ABIWindows_x86_64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { const int32_t ptr_size = 8; row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset(0); + row->SetUnspecifiedRegistersAreUndefined(true); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp new file mode 100644 index 000000000000..9994cc293d6a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.cpp @@ -0,0 +1,45 @@ +//===-- ArchitectureAArch64.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/AArch64/ArchitectureAArch64.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Utility/ArchSpec.h" + +using namespace lldb_private; +using namespace lldb; + +LLDB_PLUGIN_DEFINE(ArchitectureAArch64) + +ConstString ArchitectureAArch64::GetPluginNameStatic() { + return ConstString("aarch64"); +} + +void ArchitectureAArch64::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "AArch64-specific algorithms", + &ArchitectureAArch64::Create); +} + +void ArchitectureAArch64::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureAArch64::Create); +} + +std::unique_ptr<Architecture> +ArchitectureAArch64::Create(const ArchSpec &arch) { + auto machine = arch.GetMachine(); + if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be && + machine != llvm::Triple::aarch64_32) { + return nullptr; + } + return std::unique_ptr<Architecture>(new ArchitectureAArch64()); +} + +ConstString ArchitectureAArch64::GetPluginName() { + return GetPluginNameStatic(); +} +uint32_t ArchitectureAArch64::GetPluginVersion() { return 1; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h new file mode 100644 index 000000000000..775478cc9338 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/AArch64/ArchitectureAArch64.h @@ -0,0 +1,40 @@ +//===-- ArchitectureAArch64.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H +#define LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H + +#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h" +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureAArch64 : public Architecture { +public: + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + void OverrideStopInfo(Thread &thread) const override{}; + + const MemoryTagManager *GetMemoryTagManager() const override { + return &m_memory_tag_manager; + } + +private: + static std::unique_ptr<Architecture> Create(const ArchSpec &arch); + ArchitectureAArch64() = default; + MemoryTagManagerAArch64MTE m_memory_tag_manager; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_ARCHITECTURE_AARCH64_ARCHITECTUREAARCH64_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp index 22508969ceed..757c91570009 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Architecture/Mips/ArchitectureMips.cpp @@ -160,7 +160,6 @@ Instruction *ArchitectureMips::GetInstructionAtAddress( InstructionList instruction_list; InstructionSP prev_insn; - bool prefer_file_cache = true; // Read from file uint32_t inst_to_choose = 0; Address addr = resolved_addr; @@ -171,8 +170,7 @@ Instruction *ArchitectureMips::GetInstructionAtAddress( uint32_t insn_size = 0; disasm_sp->ParseInstructions(target, addr, - {Disassembler::Limit::Bytes, i * 2}, nullptr, - prefer_file_cache); + {Disassembler::Limit::Bytes, i * 2}, nullptr); uint32_t num_insns = disasm_sp->GetInstructionList().GetSize(); if (num_insns) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp index 8a2d3232a39a..7cd505d0ed29 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -905,7 +905,8 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu, return Instance(); std::unique_ptr<llvm::MCContext> context_up( - new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), nullptr)); + new llvm::MCContext(llvm::Triple(triple), asm_info_up.get(), + reg_info_up.get(), subtarget_info_up.get())); if (!context_up) return Instance(); diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h index 5707f8858f6c..c34e02ed5678 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h @@ -35,15 +35,13 @@ class HexagonDYLDRendezvous { // the layout of this struct is not binary compatible, it is simply large // enough to hold the information on both 32 and 64 bit platforms. struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; - - Rendezvous() - : version(0), map_addr(LLDB_INVALID_ADDRESS), brk(LLDB_INVALID_ADDRESS), - state(0), ldbase(0) {} + uint64_t version = 0; + lldb::addr_t map_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t brk = LLDB_INVALID_ADDRESS; + uint64_t state = 0; + lldb::addr_t ldbase = 0; + + Rendezvous() = default; }; public: diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h index 3e88d88f407a..5775f5a730cd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h @@ -38,13 +38,13 @@ class DYLDRendezvous { // the layout of this struct is not binary compatible, it is simply large // enough to hold the information on both 32 and 64 bit platforms. struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; + uint64_t version = 0; + lldb::addr_t map_addr = 0; + lldb::addr_t brk = 0; + uint64_t state = 0; + lldb::addr_t ldbase = 0; - Rendezvous() : version(0), map_addr(0), brk(0), state(0), ldbase(0) {} + Rendezvous() = default; }; public: diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp index c1fceeb1482c..8a5528f1e474 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "DynamicLoaderStatic.h" @@ -105,6 +106,15 @@ void DynamicLoaderStatic::LoadAllImagesAtFileAddresses() { // the file... SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx)); if (section_sp) { + // If this section already has a load address set in the target, + // don't re-set it to the file address. Something may have + // set it to a more correct value already. + if (m_process->GetTarget() + .GetSectionLoadList() + .GetSectionLoadAddress(section_sp) != + LLDB_INVALID_ADDRESS) { + continue; + } if (m_process->GetTarget().SetSectionLoadAddress( section_sp, section_sp->GetFileAddress())) changed = true; diff --git a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index 7f9504b9b3a9..54dfa3e9d6f2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -28,7 +28,7 @@ LLDB_PLUGIN_DEFINE(DynamicLoaderWindowsDYLD) DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process) : DynamicLoader(process) {} -DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() {} +DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() = default; void DynamicLoaderWindowsDYLD::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), @@ -193,7 +193,7 @@ DynamicLoaderWindowsDYLD::GetStepThroughTrampolinePlan(Thread &thread, AddressRange range(pc, 2 * 15); DisassemblerSP disassembler_sp = Disassembler::DisassembleRange( - arch, nullptr, nullptr, m_process->GetTarget(), range, true); + arch, nullptr, nullptr, m_process->GetTarget(), range); if (!disassembler_sp) { return ThreadPlanSP(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 3edbc4ab98c0..85e2fcfc838c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -15,7 +15,6 @@ #include "lldb/Target/Target.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" -#include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -27,6 +26,7 @@ #include "clang/Sema/SemaDiagnostic.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" +#include <cstdlib> using namespace llvm; using namespace clang; @@ -43,7 +43,7 @@ ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } -ASTResultSynthesizer::~ASTResultSynthesizer() {} +ASTResultSynthesizer::~ASTResultSynthesizer() = default; void ASTResultSynthesizer::Initialize(ASTContext &Context) { m_ast_context = &Context; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp index 40f0de40da52..a2722db5d24a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -9,7 +9,6 @@ #include "ASTStructExtractor.h" #include "lldb/Utility/Log.h" -#include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" @@ -21,6 +20,7 @@ #include "clang/Sema/Sema.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" +#include <cstdlib> using namespace llvm; using namespace clang; @@ -38,7 +38,7 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); } -ASTStructExtractor::~ASTStructExtractor() {} +ASTStructExtractor::~ASTStructExtractor() = default; void ASTStructExtractor::Initialize(ASTContext &Context) { m_ast_context = &Context; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp index 1e438ed9d73e..a95fce1c5aa9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.cpp @@ -8,17 +8,17 @@ #include "ASTUtils.h" -lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() {} +lldb_private::ExternalASTSourceWrapper::~ExternalASTSourceWrapper() = default; void lldb_private::ExternalASTSourceWrapper::PrintStats() { m_Source->PrintStats(); } -lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() {} +lldb_private::ASTConsumerForwarder::~ASTConsumerForwarder() = default; void lldb_private::ASTConsumerForwarder::PrintStats() { m_c->PrintStats(); } -lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() {} +lldb_private::SemaSourceWithPriorities::~SemaSourceWithPriorities() = default; void lldb_private::SemaSourceWithPriorities::PrintStats() { for (size_t i = 0; i < Sources.size(); ++i) diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index e2601a059bb7..94647b0ef978 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -184,7 +184,7 @@ private: } public: - DeclContextOverride() {} + DeclContextOverride() = default; void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) { for (DeclContext *decl_context = decl->getLexicalDeclContext(); @@ -359,9 +359,6 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { if (!ClangUtil::IsClangType(type)) return false; - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - clang::QualType qual_type( ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); @@ -435,8 +432,6 @@ bool ClangASTImporter::CanImport(const CompilerType &type) { bool ClangASTImporter::Import(const CompilerType &type) { if (!ClangUtil::IsClangType(type)) return false; - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the clang::QualType qual_type( ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); @@ -830,6 +825,10 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { // Check which ASTContext this declaration originally came from. DeclOrigin origin = m_master.GetDeclOrigin(From); + + // Prevent infinite recursion when the origin tracking contains a cycle. + assert(origin.decl != From && "Origin points to itself?"); + // If it originally came from the target ASTContext then we can just // pretend that the original is the one we imported. This can happen for // example when inspecting a persistent declaration from the scratch @@ -889,6 +888,37 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { LLDB_LOG(log, "[ClangASTImporter] Complete definition not found"); } + // Disable the minimal import for fields that have record types. There is + // no point in minimally importing the record behind their type as Clang + // will anyway request their definition when the FieldDecl is added to the + // RecordDecl (as Clang will query the FieldDecl's type for things such + // as a deleted constexpr destructor). + // By importing the type ahead of time we avoid some corner cases where + // the FieldDecl's record is importing in the middle of Clang's + // `DeclContext::addDecl` logic. + if (clang::FieldDecl *fd = dyn_cast<FieldDecl>(From)) { + // This is only necessary because we do the 'minimal import'. Remove this + // once LLDB stopped using that mode. + assert(isMinimalImport() && "Only necessary for minimal import"); + QualType field_type = fd->getType(); + if (field_type->isRecordType()) { + // First get the underlying record and minimally import it. + clang::TagDecl *record_decl = field_type->getAsTagDecl(); + llvm::Expected<Decl *> imported = Import(record_decl); + if (!imported) + return imported.takeError(); + // Check how/if the import got redirected to a different AST. Now + // import the definition of what was actually imported. If there is no + // origin then that means the record was imported by just picking a + // compatible type in the target AST (in which case there is no more + // importing to do). + if (clang::Decl *origin = m_master.GetDeclOrigin(*imported).decl) { + if (llvm::Error def_err = ImportDefinition(record_decl)) + return std::move(def_err); + } + } + } + return ASTImporter::ImportImpl(From); } @@ -904,16 +934,6 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( MapImported(from, to); ASTImporter::Imported(from, to); - /* - if (to_objc_interface) - to_objc_interface->startDefinition(); - - CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to); - - if (to_cxx_record) - to_cxx_record->startDefinition(); - */ - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); if (llvm::Error err = ImportDefinition(from)) { @@ -1088,22 +1108,23 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, DeclOrigin origin = from_context_md->getOrigin(from); if (origin.Valid()) { - if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID) - if (origin.ctx != &to->getASTContext()) + if (origin.ctx != &to->getASTContext()) { + if (!to_context_md->hasOrigin(to) || user_id != LLDB_INVALID_UID) to_context_md->setOrigin(to, origin); - ImporterDelegateSP direct_completer = - m_master.GetDelegate(&to->getASTContext(), origin.ctx); + ImporterDelegateSP direct_completer = + m_master.GetDelegate(&to->getASTContext(), origin.ctx); - if (direct_completer.get() != this) - direct_completer->ASTImporter::Imported(origin.decl, to); + if (direct_completer.get() != this) + direct_completer->ASTImporter::Imported(origin.decl, to); - LLDB_LOG(log, - " [ClangASTImporter] Propagated origin " - "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to " - "(ASTContext*){3}", - origin.decl, origin.ctx, &from->getASTContext(), - &to->getASTContext()); + LLDB_LOG(log, + " [ClangASTImporter] Propagated origin " + "(Decl*){0}/(ASTContext*){1} from (ASTContext*){2} to " + "(ASTContext*){3}", + origin.decl, origin.ctx, &from->getASTContext(), + &to->getASTContext()); + } } else { if (m_new_decl_listener) m_new_decl_listener->NewDeclImported(from, to); diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h index bf4ad174cf9c..4f589d34aa48 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h @@ -23,6 +23,7 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-types.h" #include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h" @@ -34,6 +35,32 @@ namespace lldb_private { class ClangASTMetadata; class TypeSystemClang; +/// Manages and observes all Clang AST node importing in LLDB. +/// +/// The ClangASTImporter takes care of two things: +/// +/// 1. Keeps track of all ASTImporter instances in LLDB. +/// +/// Clang's ASTImporter takes care of importing types from one ASTContext to +/// another. This class expands this concept by allowing copying from several +/// ASTContext instances to several other ASTContext instances. Instead of +/// constructing a new ASTImporter manually to copy over a type/decl, this class +/// can be asked to do this. It will construct a ASTImporter for the caller (and +/// will cache the ASTImporter instance for later use) and then perform the +/// import. +/// +/// This mainly prevents that a caller might construct several ASTImporter +/// instances for the same source/target ASTContext combination. As the +/// ASTImporter has an internal state that keeps track of already imported +/// declarations and so on, using only one ASTImporter instance is more +/// efficient and less error-prone than using multiple. +/// +/// 2. Keeps track of from where declarations were imported (origin-tracking). +/// The ASTImporter instances in this class usually only performa a minimal +/// import, i.e., only a shallow copy is made that is filled out on demand +/// when more information is requested later on. This requires record-keeping +/// of where any shallow clone originally came from so that the right original +/// declaration can be found and used as the source of any missing information. class ClangASTImporter { public: struct LayoutInfo { @@ -52,12 +79,34 @@ public: : m_file_manager(clang::FileSystemOptions(), FileSystem::Instance().GetVirtualFileSystem()) {} + /// Copies the given type and the respective declarations to the destination + /// type system. + /// + /// This function does a shallow copy and requires that the target AST + /// has an ExternalASTSource which queries this ClangASTImporter instance + /// for any additional information that is maybe lacking in the shallow copy. + /// This also means that the type system of src_type can *not* be deleted + /// after this function has been called. If you need to delete the source + /// type system you either need to delete the destination type system first + /// or use \ref ClangASTImporter::DeportType. + /// + /// \see ClangASTImporter::DeportType CompilerType CopyType(TypeSystemClang &dst, const CompilerType &src_type); + /// \see ClangASTImporter::CopyType clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::Decl *decl); + /// Copies the given type and the respective declarations to the destination + /// type system. + /// + /// Unlike CopyType this function ensures that types/declarations which are + /// originally from the AST of src_type are fully copied over. The type + /// system of src_type can safely be deleted after calling this function. + /// \see ClangASTImporter::CopyType CompilerType DeportType(TypeSystemClang &dst, const CompilerType &src_type); + /// Copies the given decl to the destination type system. + /// \see ClangASTImporter::DeportType clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, clang::Decl *decl); /// Sets the layout for the given RecordDecl. The layout will later be @@ -78,8 +127,22 @@ public: llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); + /// Returns true iff the given type was copied from another TypeSystemClang + /// and the original type in this other TypeSystemClang might contain + /// additional information (e.g., the definition of a 'class' type) that could + /// be imported. + /// + /// \see ClangASTImporter::Import bool CanImport(const CompilerType &type); + /// If the given type was copied from another TypeSystemClang then copy over + /// all missing information (e.g., the definition of a 'class' type). + /// + /// \return True iff an original type in another TypeSystemClang was found. + /// Note: Does *not* return false if an original type was found but + /// no information was imported over. + /// + /// \see ClangASTImporter::Import bool Import(const CompilerType &type); bool CompleteType(const CompilerType &compiler_type); @@ -94,6 +157,14 @@ public: bool RequireCompleteType(clang::QualType type); + /// Updates the internal origin-tracking information so that the given + /// 'original' decl is from now on used to import additional information + /// into the given decl. + /// + /// Usually the origin-tracking in the ClangASTImporter is automatically + /// updated when a declaration is imported, so the only valid reason to ever + /// call this is if there is a 'better' original decl and the target decl + /// is only a shallow clone that lacks any contents. void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl); ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl); @@ -145,10 +216,13 @@ public: void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); struct DeclOrigin { - DeclOrigin() : ctx(nullptr), decl(nullptr) {} + DeclOrigin() = default; DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl) - : ctx(_ctx), decl(_decl) {} + : ctx(_ctx), decl(_decl) { + // The decl has to be in its associated ASTContext. + assert(_decl == nullptr || &_decl->getASTContext() == _ctx); + } DeclOrigin(const DeclOrigin &rhs) { ctx = rhs.ctx; @@ -162,8 +236,8 @@ public: bool Valid() const { return (ctx != nullptr || decl != nullptr); } - clang::ASTContext *ctx; - clang::Decl *decl; + clang::ASTContext *ctx = nullptr; + clang::Decl *decl = nullptr; }; /// Listener interface used by the ASTImporterDelegate to inform other code @@ -190,6 +264,16 @@ public: : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx, master.m_file_manager, true /*minimal*/), m_master(master), m_source_ctx(source_ctx) { + // Target and source ASTContext shouldn't be identical. Importing AST + // nodes within the same AST doesn't make any sense as the whole idea + // is to import them to a different AST. + lldbassert(target_ctx != source_ctx && "Can't import into itself"); + // This is always doing a minimal import of any declarations. This means + // that there has to be an ExternalASTSource in the target ASTContext + // (that should implement the callbacks that complete any declarations + // on demand). Without an ExternalASTSource, this ASTImporter will just + // do a minimal import and the imported declarations won't be completed. + assert(target_ctx->getExternalSource() && "Missing ExternalSource"); setODRHandling(clang::ASTImporter::ODRHandlingType::Liberal); } @@ -272,6 +356,13 @@ public: /// Sets the DeclOrigin for the given Decl and overwrites any existing /// DeclOrigin. void setOrigin(const clang::Decl *decl, DeclOrigin origin) { + // Setting the origin of any decl to itself (or to a different decl + // in the same ASTContext) doesn't make any sense. It will also cause + // ASTImporterDelegate::ImportImpl to infinite recurse when trying to find + // the 'original' Decl when importing code. + assert(&decl->getASTContext() != origin.ctx && + "Trying to set decl origin to its own ASTContext?"); + assert(decl != origin.decl && "Trying to set decl origin to itself?"); m_origins[decl] = origin; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 0f34c48c7e82..b43423707ae1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -479,10 +479,7 @@ void ClangASTSource::FindExternalLexicalDecls( decl->getDeclKindName(), ast_dump); } - Decl *copied_decl = CopyDecl(decl); - - if (!copied_decl) - continue; + CopyDecl(decl); // FIXME: We should add the copied decl to the 'decls' list. This would // add the copied Decl into the DeclContext and make sure that we @@ -492,12 +489,6 @@ void ClangASTSource::FindExternalLexicalDecls( // lookup issues later on. // We can't just add them for now as the ASTImporter already added the // decl into the DeclContext and this would add it twice. - - if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) { - QualType copied_field_type = copied_field->getType(); - - m_ast_importer_sp->RequireCompleteType(copied_field_type); - } } else { SkippedDecls = true; } @@ -850,8 +841,8 @@ void ClangASTSource::FindDeclInModules(NameSearchContext &context, ConstString name) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - ClangModulesDeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor(); + std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor = + GetClangModulesDeclVendor(); if (!modules_decl_vendor) return; @@ -1143,8 +1134,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { // Check the modules only if the debug information didn't have a complete // interface. - if (ClangModulesDeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor()) { + if (std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor = + GetClangModulesDeclVendor()) { ConstString interface_name(interface_decl->getNameAsString().c_str()); bool append = false; uint32_t max_matches = 1; @@ -1313,8 +1304,8 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { // Check the modules only if the debug information didn't have a complete // interface. - ClangModulesDeclVendor *modules_decl_vendor = - m_target->GetClangModulesDeclVendor(); + std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor = + GetClangModulesDeclVendor(); if (!modules_decl_vendor) break; @@ -1570,10 +1561,10 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, if (log) { LLDB_LOG(log, "LRT returned:"); - LLDB_LOG(log, "LRT Original = (RecordDecl*)%p", + LLDB_LOG(log, "LRT Original = (RecordDecl*){0}", static_cast<const void *>(origin_record.decl)); - LLDB_LOG(log, "LRT Size = %" PRId64, size); - LLDB_LOG(log, "LRT Alignment = %" PRId64, alignment); + LLDB_LOG(log, "LRT Size = {0}", size); + LLDB_LOG(log, "LRT Alignment = {0}", alignment); LLDB_LOG(log, "LRT Fields:"); for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); @@ -1750,3 +1741,10 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { return m_clang_ast_context->GetType(copied_qual_type); } + +std::shared_ptr<ClangModulesDeclVendor> +ClangASTSource::GetClangModulesDeclVendor() { + auto persistent_vars = llvm::cast<ClangPersistentVariables>( + m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + return persistent_vars->GetClangModulesDeclVendor(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 14761fbeb26b..3afd1fd5f2d1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -314,6 +314,8 @@ protected: /// The imported type. CompilerType GuardedCopyType(const CompilerType &src_type); + std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor(); + public: /// Returns true if a name should be ignored by name lookup. /// diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h index bf52bec4b1fa..6313117c08d6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h @@ -22,7 +22,7 @@ class ClangDeclVendor : public DeclVendor { public: ClangDeclVendor(DeclVendorKind kind) : DeclVendor(kind) {} - virtual ~ClangDeclVendor() {} + virtual ~ClangDeclVendor() = default; using DeclVendor::FindDecls; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 852ce3bbd3db..731b81c61a6f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -350,7 +350,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, if (!var) return false; - LLDB_LOG(log, "Adding value for (NamedDecl*)%p [%s - %s] to the structure", + LLDB_LOG(log, "Adding value for (NamedDecl*){0} [{1} - {2}] to the structure", decl, name, var->GetName()); // We know entity->m_parser_vars is valid because we used a parser variable @@ -752,7 +752,7 @@ void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context, MaybeRegisterFunctionBody(parser_function_decl); } - LLDB_LOG(log, " CEDM::FEVD Found persistent decl %s", name); + LLDB_LOG(log, " CEDM::FEVD Found persistent decl {0}", name); context.AddNamedDecl(parser_named_decl); } @@ -1021,7 +1021,8 @@ void ClangExpressionDeclMap::LookupInModulesDeclVendor( if (!m_target) return; - auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); + std::shared_ptr<ClangModulesDeclVendor> modules_decl_vendor = + GetClangModulesDeclVendor(); if (!modules_decl_vendor) return; @@ -1213,8 +1214,8 @@ void ClangExpressionDeclMap::LookupFunction( std::vector<clang::NamedDecl *> decls_from_modules; if (target) { - if (ClangModulesDeclVendor *decl_vendor = - target->GetClangModulesDeclVendor()) { + if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor = + GetClangModulesDeclVendor()) { decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); } } @@ -1493,7 +1494,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, if (var_location_expr.GetExpressionData(const_value_extractor)) { var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); - var_location.SetValueType(Value::eValueTypeHostAddress); + var_location.SetValueType(Value::ValueType::HostAddress); } else { LLDB_LOG(log, "Error evaluating constant variable: {0}", err.AsCString()); return false; @@ -1512,10 +1513,10 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, if (parser_type) *parser_type = TypeFromParser(type_to_use); - if (var_location.GetContextType() == Value::eContextTypeInvalid) + if (var_location.GetContextType() == Value::ContextType::Invalid) var_location.SetCompilerType(type_to_use); - if (var_location.GetValueType() == Value::eValueTypeFileAddress) { + if (var_location.GetValueType() == Value::ValueType::FileAddress) { SymbolContext var_sc; var->CalculateSymbolContext(&var_sc); @@ -1529,7 +1530,7 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, if (load_addr != LLDB_INVALID_ADDRESS) { var_location.GetScalar() = load_addr; - var_location.SetValueType(Value::eValueTypeLoadAddress); + var_location.SetValueType(Value::ValueType::LoadAddress); } } @@ -1665,11 +1666,11 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, const Address symbol_address = symbol.GetAddress(); lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); - // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, + // parser_vars->m_lldb_value.SetContext(Value::ContextType::ClangType, // user_type.GetOpaqueQualType()); parser_vars->m_lldb_value.SetCompilerType(user_type); parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); parser_vars->m_named_decl = var_decl; parser_vars->m_llvm_value = nullptr; @@ -1860,14 +1861,14 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, entity->GetParserVars(GetParserID()); if (load_addr != LLDB_INVALID_ADDRESS) { - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + parser_vars->m_lldb_value.SetValueType(Value::ValueType::LoadAddress); parser_vars->m_lldb_value.GetScalar() = load_addr; } else { // We have to try finding a file address. lldb::addr_t file_addr = fun_address.GetFileAddress(); - parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); + parser_vars->m_lldb_value.SetValueType(Value::ValueType::FileAddress); parser_vars->m_lldb_value.GetScalar() = file_addr; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index a9cd5d166b9d..e39dc587bc43 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -9,8 +9,8 @@ #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H -#include <signal.h> -#include <stdint.h> +#include <csignal> +#include <cstdint> #include <vector> @@ -248,10 +248,10 @@ public: lldb::SymbolType symbol_type); struct TargetInfo { - lldb::ByteOrder byte_order; - size_t address_byte_size; + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid; + size_t address_byte_size = 0; - TargetInfo() : byte_order(lldb::eByteOrderInvalid), address_byte_size(0) {} + TargetInfo() = default; bool IsValid() { return (byte_order != lldb::eByteOrderInvalid && address_byte_size != 0); @@ -308,7 +308,7 @@ private: /// The following values should not live beyond parsing class ParserVars { public: - ParserVars() {} + ParserVars() = default; Target *GetTarget() { if (m_exe_ctx.GetTargetPtr()) @@ -353,16 +353,15 @@ private: /// The following values contain layout information for the materialized /// struct, but are not specific to a single materialization struct StructVars { - StructVars() - : m_struct_alignment(0), m_struct_size(0), m_struct_laid_out(false), - m_result_name(), m_object_pointer_type(nullptr, nullptr) {} - - lldb::offset_t - m_struct_alignment; ///< The alignment of the struct in bytes. - size_t m_struct_size; ///< The size of the struct in bytes. - bool m_struct_laid_out; ///< True if the struct has been laid out and the - ///layout is valid (that is, no new fields have been - ///added since). + StructVars() : m_result_name(), m_object_pointer_type(nullptr, nullptr) {} + + lldb::offset_t m_struct_alignment = + 0; ///< The alignment of the struct in bytes. + size_t m_struct_size = 0; ///< The size of the struct in bytes. + bool m_struct_laid_out = + false; ///< True if the struct has been laid out and the + /// layout is valid (that is, no new fields have been + /// added since). ConstString m_result_name; ///< The name of the result variable ($1, for example) TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h index e33e5df22236..37bcaf000cfc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -38,7 +38,7 @@ public: ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) {} /// Destructor - virtual ~ClangExpressionHelper() {} + virtual ~ClangExpressionHelper() = default; /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 7644a5e1423e..0b5e1ab059d2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -343,6 +343,7 @@ static void SetupDefaultClangDiagnostics(CompilerInstance &compiler) { const std::vector<const char *> groupsToIgnore = { "unused-value", "odr", + "unused-getter-return-value", }; for (const char *group : groupsToIgnore) { compiler.getDiagnostics().setSeverityForGroup( @@ -513,7 +514,7 @@ ClangExpressionParser::ClangExpressionParser( LLDB_LOGF(log, "Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); LLDB_LOGF(log, "Target datalayout string: '%s'", - target_info->getDataLayout().getStringRepresentation().c_str()); + target_info->getDataLayoutString()); LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str()); LLDB_LOGF(log, "Target vector alignment: %d", target_info->getMaxVectorAlign()); @@ -657,7 +658,8 @@ ClangExpressionParser::ClangExpressionParser( // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. - m_compiler->getTarget().adjust(m_compiler->getLangOpts()); + m_compiler->getTarget().adjust(m_compiler->getDiagnostics(), + m_compiler->getLangOpts()); // 6. Set up the diagnostic buffer for reporting errors @@ -686,11 +688,11 @@ ClangExpressionParser::ClangExpressionParser( break; } - if (ClangModulesDeclVendor *decl_vendor = - target_sp->GetClangModulesDeclVendor()) { - if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>( - target_sp->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC))) { + if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>( + target_sp->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC))) { + if (std::shared_ptr<ClangModulesDeclVendor> decl_vendor = + clang_persistent_vars->GetClangModulesDeclVendor()) { std::unique_ptr<PPCallbacks> pp_callbacks( new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager())); @@ -723,7 +725,7 @@ ClangExpressionParser::ClangExpressionParser( m_compiler->getCodeGenOpts(), *m_llvm_context)); } -ClangExpressionParser::~ClangExpressionParser() {} +ClangExpressionParser::~ClangExpressionParser() = default; namespace { diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 180e08b03c93..31707f81a270 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -31,6 +31,7 @@ using namespace lldb_private; #define PREFIX_NAME "<lldb wrapper prefix>" +#define SUFFIX_NAME "<lldb wrapper suffix>" const llvm::StringRef ClangExpressionSourceCode::g_prefix_file_name = PREFIX_NAME; @@ -73,6 +74,9 @@ extern "C" } )"; +const char *ClangExpressionSourceCode::g_expression_suffix = + "\n;\n#line 1 \"" SUFFIX_NAME "\"\n"; + namespace { class AddMacroState { @@ -180,7 +184,7 @@ lldb_private::ClangExpressionSourceCode::ClangExpressionSourceCode( // containing only the user expression. This will hide our wrapper code // from the user when we render diagnostics with Clang. m_start_marker = "#line 1 \"" + filename.str() + "\"\n"; - m_end_marker = "\n;\n#line 1 \"<lldb wrapper suffix>\"\n"; + m_end_marker = g_expression_suffix; } namespace { @@ -314,10 +318,11 @@ bool ClangExpressionSourceCode::GetText( } } - ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor(); auto *persistent_vars = llvm::cast<ClangPersistentVariables>( target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); - if (decl_vendor && persistent_vars) { + std::shared_ptr<ClangModulesDeclVendor> decl_vendor = + persistent_vars->GetClangModulesDeclVendor(); + if (decl_vendor) { const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index 9a54f0e3ad8d..54ae837fb30f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -27,6 +27,7 @@ public: /// the user expression. static const llvm::StringRef g_prefix_file_name; static const char *g_expression_prefix; + static const char *g_expression_suffix; /// The possible ways an expression can be wrapped. enum class WrapKind { diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index 58d589962abe..7bb68e78373f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -9,9 +9,9 @@ #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONVARIABLE_H -#include <signal.h> -#include <stdint.h> -#include <string.h> +#include <csignal> +#include <cstdint> +#include <cstring> #include <map> #include <string> @@ -116,19 +116,19 @@ public: /// The following values should not live beyond parsing class ParserVars { public: - ParserVars() - : m_named_decl(nullptr), m_llvm_value(nullptr), - m_lldb_value(), m_lldb_var(), m_lldb_sym(nullptr) {} - - const clang::NamedDecl - *m_named_decl; ///< The Decl corresponding to this variable - llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; - ///usually a GlobalValue + ParserVars() : m_lldb_value(), m_lldb_var() {} + + const clang::NamedDecl *m_named_decl = + nullptr; ///< The Decl corresponding to this variable + llvm::Value *m_llvm_value = + nullptr; ///< The IR value corresponding to this variable; + /// usually a GlobalValue lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable lldb::VariableSP m_lldb_var; ///< The original variable for this variable - const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this - ///variable, if it was a symbol + const lldb_private::Symbol *m_lldb_sym = + nullptr; ///< The original symbol for this + /// variable, if it was a symbol }; private: @@ -157,13 +157,13 @@ public: /// The following values are valid if the variable is used by JIT code struct JITVars { - JITVars() : m_alignment(0), m_size(0), m_offset(0) {} + JITVars() = default; - lldb::offset_t - m_alignment; ///< The required alignment of the variable, in bytes - size_t m_size; ///< The space required for the variable, in bytes - lldb::offset_t - m_offset; ///< The offset of the variable in the struct, in bytes + lldb::offset_t m_alignment = + 0; ///< The required alignment of the variable, in bytes + size_t m_size = 0; ///< The space required for the variable, in bytes + lldb::offset_t m_offset = + 0; ///< The offset of the variable in the struct, in bytes }; private: diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index 0c9ad2021035..2cfa9a4c9ccf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -59,7 +59,7 @@ ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope, } // Destructor -ClangFunctionCaller::~ClangFunctionCaller() {} +ClangFunctionCaller::~ClangFunctionCaller() = default; unsigned diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index c014ad504d37..336058a5abb9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -42,9 +42,9 @@ using namespace lldb_private; namespace { -// Any Clang compiler requires a consumer for diagnostics. This one stores -// them as strings so we can provide them to the user in case a module failed -// to load. +/// Any Clang compiler requires a consumer for diagnostics. This one stores +/// them as strings so we can provide them to the user in case a module failed +/// to load. class StoringDiagnosticConsumer : public clang::DiagnosticConsumer { public: StoringDiagnosticConsumer(); @@ -74,8 +74,8 @@ private: Log *m_log; }; -// The private implementation of our ClangModulesDeclVendor. Contains all the -// Clang state required to load modules. +/// The private implementation of our ClangModulesDeclVendor. Contains all the +/// Clang state required to load modules. class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor { public: ClangModulesDeclVendorImpl( @@ -100,9 +100,9 @@ public: std::function<bool(llvm::StringRef, llvm::StringRef)> handler) override; private: - void - ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports, - clang::Module *module); + typedef llvm::DenseSet<ModuleID> ExportedModuleSet; + void ReportModuleExportsHelper(ExportedModuleSet &exports, + clang::Module *module); void ReportModuleExports(ModuleVector &exports, clang::Module *module); @@ -120,7 +120,7 @@ private: typedef std::vector<ConstString> ImportedModule; typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap; - typedef std::set<ModuleID> ImportedModuleSet; + typedef llvm::DenseSet<ModuleID> ImportedModuleSet; ImportedModuleMap m_imported_modules; ImportedModuleSet m_user_imported_modules; // We assume that every ASTContext has an TypeSystemClang, so we also store @@ -176,7 +176,7 @@ void StoringDiagnosticConsumer::EndSourceFile() { ClangModulesDeclVendor::ClangModulesDeclVendor() : ClangDeclVendor(eClangModuleDeclVendor) {} -ClangModulesDeclVendor::~ClangModulesDeclVendor() {} +ClangModulesDeclVendor::~ClangModulesDeclVendor() = default; ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine, @@ -195,8 +195,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( } void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( - std::set<ClangModulesDeclVendor::ModuleID> &exports, - clang::Module *module) { + ExportedModuleSet &exports, clang::Module *module) { if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module))) return; @@ -206,20 +205,18 @@ void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( module->getExportedModules(sub_exports); - for (clang::Module *module : sub_exports) { + for (clang::Module *module : sub_exports) ReportModuleExportsHelper(exports, module); - } } void ClangModulesDeclVendorImpl::ReportModuleExports( ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) { - std::set<ClangModulesDeclVendor::ModuleID> exports_set; + ExportedModuleSet exports_set; ReportModuleExportsHelper(exports_set, module); - for (ModuleID module : exports_set) { + for (ModuleID module : exports_set) exports.push_back(module); - } } bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, @@ -237,17 +234,15 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, std::vector<ConstString> imported_module; - for (ConstString path_component : module.path) { + for (ConstString path_component : module.path) imported_module.push_back(path_component); - } { ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); if (mi != m_imported_modules.end()) { - if (exported_modules) { + if (exported_modules) ReportModuleExports(*exported_modules, mi->second); - } return true; } } @@ -338,9 +333,8 @@ bool ClangModulesDeclVendorImpl::AddModule(const SourceModule &module, clang::Module *requested_module = DoGetModule(clang_path, true); if (requested_module != nullptr) { - if (exported_modules) { + if (exported_modules) ReportModuleExports(*exported_modules, requested_module); - } m_imported_modules[imported_module] = requested_module; @@ -388,9 +382,8 @@ uint32_t ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append, uint32_t max_matches, std::vector<CompilerDecl> &decls) { - if (!m_enabled) { + if (!m_enabled) return 0; - } if (!append) decls.clear(); @@ -423,18 +416,16 @@ ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append, void ClangModulesDeclVendorImpl::ForEachMacro( const ClangModulesDeclVendor::ModuleVector &modules, std::function<bool(llvm::StringRef, llvm::StringRef)> handler) { - if (!m_enabled) { + if (!m_enabled) return; - } typedef std::map<ModuleID, ssize_t> ModulePriorityMap; ModulePriorityMap module_priorities; ssize_t priority = 0; - for (ModuleID module : modules) { + for (ModuleID module : modules) module_priorities[module] = priority++; - } if (m_compiler_instance->getPreprocessor().getExternalSource()) { m_compiler_instance->getPreprocessor() @@ -455,9 +446,8 @@ void ClangModulesDeclVendorImpl::ForEachMacro( .getExternalIdentifierLookup()) { lookup->get(mi->first->getName()); } - if (!ii) { + if (!ii) ii = mi->first; - } } ssize_t found_priority = -1; @@ -504,24 +494,21 @@ void ClangModulesDeclVendorImpl::ForEachMacro( for (auto pi = macro_info->param_begin(), pe = macro_info->param_end(); pi != pe; ++pi) { - if (!first_arg) { + if (!first_arg) macro_expansion.append(", "); - } else { + else first_arg = false; - } macro_expansion.append((*pi)->getName().str()); } if (macro_info->isC99Varargs()) { - if (first_arg) { + if (first_arg) macro_expansion.append("..."); - } else { + else macro_expansion.append(", ..."); - } - } else if (macro_info->isGNUVarargs()) { + } else if (macro_info->isGNUVarargs()) macro_expansion.append("..."); - } macro_expansion.append(")"); } @@ -533,11 +520,10 @@ void ClangModulesDeclVendorImpl::ForEachMacro( for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), te = macro_info->tokens_end(); ti != te; ++ti) { - if (!first_token) { + if (!first_token) macro_expansion.append(" "); - } else { + else first_token = false; - } if (ti->isLiteral()) { if (const char *literal_data = ti->getLiteralData()) { @@ -718,7 +704,7 @@ ClangModulesDeclVendor::Create(Target &target) { if (!instance->hasTarget()) return nullptr; - instance->getTarget().adjust(instance->getLangOpts()); + instance->getTarget().adjust(*diagnostics_engine, instance->getLangOpts()); if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 42afac9edb0d..13d6a37113b8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -8,6 +8,7 @@ #include "ClangPersistentVariables.h" #include "ClangASTImporter.h" +#include "ClangModulesDeclVendor.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Value.h" @@ -23,8 +24,10 @@ using namespace lldb; using namespace lldb_private; -ClangPersistentVariables::ClangPersistentVariables() - : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang) {} +ClangPersistentVariables::ClangPersistentVariables( + std::shared_ptr<Target> target_sp) + : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), + m_target_sp(target_sp) {} ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable( const lldb::ValueObjectSP &valobj_sp) { @@ -109,6 +112,15 @@ ClangPersistentVariables::GetClangASTImporter() { return m_ast_importer_sp; } +std::shared_ptr<ClangModulesDeclVendor> +ClangPersistentVariables::GetClangModulesDeclVendor() { + if (!m_modules_decl_vendor_sp) { + m_modules_decl_vendor_sp.reset( + ClangModulesDeclVendor::Create(*m_target_sp.get())); + } + return m_modules_decl_vendor_sp; +} + ConstString ClangPersistentVariables::GetNextPersistentVariableName(bool is_error) { llvm::SmallString<64> name; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index f888b2d56e68..b8a359d05f75 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -19,6 +19,8 @@ namespace lldb_private { class ClangASTImporter; +class ClangModulesDeclVendor; +class Target; class TypeSystemClang; /// \class ClangPersistentVariables ClangPersistentVariables.h @@ -30,7 +32,7 @@ class TypeSystemClang; /// 0-based counter for naming result variables. class ClangPersistentVariables : public PersistentExpressionState { public: - ClangPersistentVariables(); + ClangPersistentVariables(std::shared_ptr<Target> target_sp); ~ClangPersistentVariables() override = default; @@ -40,6 +42,7 @@ public: } std::shared_ptr<ClangASTImporter> GetClangASTImporter(); + std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor(); lldb::ExpressionVariableSP CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) override; @@ -106,6 +109,8 @@ private: ///these are the highest- ///< priority source for macros. std::shared_ptr<ClangASTImporter> m_ast_importer_sp; + std::shared_ptr<ClangModulesDeclVendor> m_modules_decl_vendor_sp; + std::shared_ptr<Target> m_target_sp; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 9be294750fa0..1b205b13113b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -8,7 +8,7 @@ #include "lldb/Host/Config.h" -#include <stdio.h> +#include <cstdio> #if HAVE_SYS_TYPES_H #include <sys/types.h> #endif @@ -90,7 +90,7 @@ ClangUserExpression::ClangUserExpression( } } -ClangUserExpression::~ClangUserExpression() {} +ClangUserExpression::~ClangUserExpression() = default; void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -349,10 +349,6 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target, DiagnosticManager &diagnostic_manager) { - ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor(); - if (!decl_vendor) - return; - if (!target->GetEnableAutoImportClangModules()) return; @@ -361,6 +357,11 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target, if (!persistent_state) return; + std::shared_ptr<ClangModulesDeclVendor> decl_vendor = + persistent_state->GetClangModulesDeclVendor(); + if (!decl_vendor) + return; + StackFrame *frame = exe_ctx.GetFramePtr(); if (!frame) return; diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index 9788a4e1c183..a78116352c2e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -14,7 +14,7 @@ #include "ClangExpressionSourceCode.h" #include "ClangPersistentVariables.h" -#include <stdio.h> +#include <cstdio> #if HAVE_SYS_TYPES_H #include <sys/types.h> #endif @@ -34,21 +34,38 @@ using namespace lldb_private; char ClangUtilityFunction::ID; -/// Constructor -/// -/// \param[in] text -/// The text of the function. Must be a full translation unit. -/// -/// \param[in] name -/// The name of the function, as used in the text. ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope, - std::string text, std::string name) + std::string text, std::string name, + bool enable_debugging) : UtilityFunction( exe_scope, - std::string(ClangExpressionSourceCode::g_expression_prefix) + text, - std::move(name)) {} + std::string(ClangExpressionSourceCode::g_expression_prefix) + text + + std::string(ClangExpressionSourceCode::g_expression_suffix), + std::move(name), enable_debugging) { + // Write the source code to a file so that LLDB's source manager can display + // it when debugging the code. + if (enable_debugging) { + int temp_fd = -1; + llvm::SmallString<128> result_path; + llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); + if (temp_fd != -1) { + lldb_private::NativeFile file(temp_fd, File::eOpenOptionWrite, true); + text = "#line 1 \"" + std::string(result_path) + "\"\n" + text; + size_t bytes_written = text.size(); + file.Write(text.c_str(), bytes_written); + if (bytes_written == text.size()) { + // If we successfully wrote the source to a temporary file, replace the + // function text with the next text containing the line directive. + m_function_text = + std::string(ClangExpressionSourceCode::g_expression_prefix) + text + + std::string(ClangExpressionSourceCode::g_expression_suffix); + } + file.Close(); + } + } +} -ClangUtilityFunction::~ClangUtilityFunction() {} +ClangUtilityFunction::~ClangUtilityFunction() = default; /// Install the utility function into a process /// diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index 7914e1406cd0..b8a154b3baed 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -48,8 +48,11 @@ public: /// /// \param[in] name /// The name of the function, as used in the text. + /// + /// \param[in] enable_debugging + /// Enable debugging of this function. ClangUtilityFunction(ExecutionContextScope &exe_scope, std::string text, - std::string name); + std::string name, bool enable_debugging); ~ClangUtilityFunction() override; @@ -71,9 +74,9 @@ public: private: class ClangUtilityFunctionHelper : public ClangExpressionHelper { public: - ClangUtilityFunctionHelper() {} + ClangUtilityFunctionHelper() = default; - ~ClangUtilityFunctionHelper() override {} + ~ClangUtilityFunctionHelper() override = default; /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h index b984db43fa6d..425106bba0a3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CppModuleConfiguration.h @@ -59,7 +59,7 @@ public: /// Creates a configuration by analyzing the given list of used source files. explicit CppModuleConfiguration(const FileSpecList &support_files); /// Creates an empty and invalid configuration. - CppModuleConfiguration() {} + CppModuleConfiguration() = default; /// Returns true iff this is a valid configuration that can be used to /// load and compile modules. diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp index f953e860969c..74dd04600b4b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/CxxModuleHandler.cpp @@ -33,6 +33,9 @@ CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target) "shared_ptr", "unique_ptr", "weak_ptr", + // iterator + "move_iterator", + "__wrap_iter", // utility "allocator", "pair", diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index b35bf07034bd..5655d548ee34 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -14,6 +14,7 @@ #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" @@ -41,14 +42,12 @@ using namespace llvm; -static char ID; - typedef SmallVector<Instruction *, 2> InstrList; IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : m_maker(maker), m_values() {} -IRForTarget::FunctionValueCache::~FunctionValueCache() {} +IRForTarget::FunctionValueCache::~FunctionValueCache() = default; llvm::Value * IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) { @@ -72,13 +71,9 @@ IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, lldb_private::IRExecutionUnit &execution_unit, lldb_private::Stream &error_stream, const char *func_name) - : ModulePass(ID), m_resolve_vars(resolve_vars), m_func_name(func_name), - m_module(nullptr), m_decl_map(decl_map), - m_CFStringCreateWithBytes(nullptr), m_sel_registerName(nullptr), - m_objc_getClass(nullptr), m_intptr_ty(nullptr), - m_error_stream(error_stream), m_execution_unit(execution_unit), - m_result_store(nullptr), m_result_is_pointer(false), - m_reloc_placeholder(nullptr), + : m_resolve_vars(resolve_vars), m_func_name(func_name), + m_decl_map(decl_map), m_error_stream(error_stream), + m_execution_unit(execution_unit), m_entry_instruction_finder(FindEntryInstruction) {} /* Handy utility functions used at several places in the code */ @@ -105,8 +100,6 @@ static std::string PrintType(const llvm::Type *type, bool truncate = false) { return s; } -IRForTarget::~IRForTarget() {} - bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) { llvm_function.setLinkage(GlobalValue::ExternalLinkage); @@ -1582,20 +1575,14 @@ bool IRForTarget::UnfoldConstant(Constant *old_constant, FunctionValueCache get_element_pointer_maker( [&value_maker, &entry_instruction_finder, old_constant, constant_expr](llvm::Function *function) -> llvm::Value * { - Value *ptr = constant_expr->getOperand(0); + auto *gep = cast<llvm::GEPOperator>(constant_expr); + Value *ptr = gep->getPointerOperand(); if (ptr == old_constant) ptr = value_maker.GetValue(function); std::vector<Value *> index_vector; - - unsigned operand_index; - unsigned num_operands = constant_expr->getNumOperands(); - - for (operand_index = 1; operand_index < num_operands; - ++operand_index) { - Value *operand = constant_expr->getOperand(operand_index); - + for (Value *operand : gep->indices()) { if (operand == old_constant) operand = value_maker.GetValue(function); @@ -1605,7 +1592,7 @@ bool IRForTarget::UnfoldConstant(Constant *old_constant, ArrayRef<Value *> indices(index_vector); return GetElementPtrInst::Create( - nullptr, ptr, indices, "", + gep->getSourceElementType(), ptr, indices, "", llvm::cast<Instruction>( entry_instruction_finder.GetValue(function))); }); @@ -1788,7 +1775,8 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { ConstantInt *offset_int( ConstantInt::get(offset_type, offset, true)); GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create( - nullptr, argument, offset_int, "", entry_instruction); + argument->getType()->getPointerElementType(), argument, + offset_int, "", entry_instruction); if (name == m_result_name && !m_result_is_pointer) { BitCastInst *bit_cast = new BitCastInst( @@ -2022,10 +2010,3 @@ bool IRForTarget::runOnModule(Module &llvm_module) { return true; } - -void IRForTarget::assignPassManager(PMStack &pass_mgr_stack, - PassManagerType pass_mgr_type) {} - -PassManagerType IRForTarget::getPotentialPassManagerType() const { - return PMT_ModulePassManager; -} diff --git a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h index ebfc0cae626c..5f212fa8f918 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -58,7 +58,7 @@ class IRMemoryMap; /// transformations to the IR which make it relocatable. These /// transformations are discussed in more detail next to their relevant /// functions. -class IRForTarget : public llvm::ModulePass { +class IRForTarget { public: enum class LookupResult { Success, Fail, Ignore }; @@ -87,9 +87,6 @@ public: lldb_private::Stream &error_stream, const char *func_name = "$__lldb_expr"); - /// Destructor - ~IRForTarget() override; - /// Run this IR transformer on a single module /// /// Implementation of the llvm::ModulePass::runOnModule() function. @@ -101,20 +98,7 @@ public: /// /// \return /// True on success; false otherwise - bool runOnModule(llvm::Module &llvm_module) override; - - /// Interface stub - /// - /// Implementation of the llvm::ModulePass::assignPassManager() function. - void assignPassManager(llvm::PMStack &pass_mgr_stack, - llvm::PassManagerType pass_mgr_type = - llvm::PMT_ModulePassManager) override; - - /// Returns PMT_ModulePassManager - /// - /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() - /// function. - llvm::PassManagerType getPotentialPassManagerType() const override; + bool runOnModule(llvm::Module &llvm_module); private: /// Ensures that the current function's linkage is set to external. @@ -419,51 +403,46 @@ private: /// True on success; false otherwise bool ReplaceVariables(llvm::Function &llvm_function); - /// Flags - bool m_resolve_vars; ///< True if external variable references and persistent - ///variable references should be resolved - lldb_private::ConstString - m_func_name; ///< The name of the function to translate - lldb_private::ConstString - m_result_name; ///< The name of the result variable ($0, $1, ...) - lldb_private::TypeFromParser - m_result_type; ///< The type of the result variable. - llvm::Module *m_module; ///< The module being processed, or NULL if that has - ///not been determined yet. - std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the - ///module being processed, or - ///NULL if there is no - ///module. - lldb_private::ClangExpressionDeclMap - *m_decl_map; ///< The DeclMap containing the Decls - llvm::FunctionCallee - m_CFStringCreateWithBytes; ///< The address of the function - /// CFStringCreateWithBytes, cast to the - /// appropriate function pointer type - llvm::FunctionCallee m_sel_registerName; ///< The address of the function - /// sel_registerName, cast to the - /// appropriate function pointer type - llvm::FunctionCallee m_objc_getClass; ///< The address of the function - /// objc_getClass, cast to the - /// appropriate function pointer type - llvm::IntegerType - *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. - lldb_private::Stream - &m_error_stream; ///< The stream on which errors should be printed - lldb_private::IRExecutionUnit & - m_execution_unit; ///< The execution unit containing the IR being created. - - llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that - ///writes to the result variable. If - /// m_has_side_effects is true, this is - /// NULL. - bool m_result_is_pointer; ///< True if the function's result in the AST is a - ///pointer (see comments in - /// ASTResultSynthesizer::SynthesizeBodyResult) - + /// True if external variable references and persistent variable references + /// should be resolved + bool m_resolve_vars; + /// The name of the function to translate + lldb_private::ConstString m_func_name; + /// The name of the result variable ($0, $1, ...) + lldb_private::ConstString m_result_name; + /// The type of the result variable. + lldb_private::TypeFromParser m_result_type; + /// The module being processed, or NULL if that has not been determined yet. + llvm::Module *m_module = nullptr; + /// The target data for the module being processed, or NULL if there is no + /// module. + std::unique_ptr<llvm::DataLayout> m_target_data; + /// The DeclMap containing the Decls + lldb_private::ClangExpressionDeclMap *m_decl_map; + /// The address of the function CFStringCreateWithBytes, cast to the + /// appropriate function pointer type + llvm::FunctionCallee m_CFStringCreateWithBytes; + /// The address of the function sel_registerName, cast to the appropriate + /// function pointer type. + llvm::FunctionCallee m_sel_registerName; + /// The address of the function objc_getClass, cast to the appropriate + /// function pointer type. + llvm::FunctionCallee m_objc_getClass; + /// The type of an integer large enough to hold a pointer. + llvm::IntegerType *m_intptr_ty = nullptr; + /// The stream on which errors should be printed. + lldb_private::Stream &m_error_stream; + /// The execution unit containing the IR being created. + lldb_private::IRExecutionUnit &m_execution_unit; + /// If non-NULL, the store instruction that writes to the result variable. If + /// m_has_side_effects is true, this is NULL. + llvm::StoreInst *m_result_store = nullptr; + /// True if the function's result in the AST is a pointer (see comments in + /// ASTResultSynthesizer::SynthesizeBodyResult) + bool m_result_is_pointer = false; /// A placeholder that will be replaced by a pointer to the final location of /// the static allocation. - llvm::GlobalVariable *m_reloc_placeholder; + llvm::GlobalVariable *m_reloc_placeholder = nullptr; class FunctionValueCache { public: diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 555912780df9..bf0bbdab740f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stdlib.h> +#include <cstdlib> #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index d15d80c97e38..dfd7c926dabf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -19,8 +19,8 @@ namespace lldb_private { // ITSession - Keep track of the IT Block progression. class ITSession { public: - ITSession() : ITCounter(0), ITState(0) {} - ~ITSession() {} + ITSession() = default; + ~ITSession() = default; // InitIT - Initializes ITCounter/ITState. bool InitIT(uint32_t bits7_0); @@ -39,8 +39,8 @@ public: uint32_t GetCond(); private: - uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4. - uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. + uint32_t ITCounter = 0; // Possible values: 0, 1, 2, 3, 4. + uint32_t ITState = 0; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. }; class EmulateInstructionARM : public EmulateInstruction { diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index aef08baa8ae9..569482c7b23b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -20,11 +20,11 @@ using namespace lldb; using namespace lldb_private; -EmulationStateARM::EmulationStateARM() : m_gpr(), m_vfp_regs(), m_memory() { +EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() { ClearPseudoRegisters(); } -EmulationStateARM::~EmulationStateARM() {} +EmulationStateARM::~EmulationStateARM() = default; bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) { RegisterContext *reg_ctx = frame.GetRegisterContext().get(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h index 955c7c642058..28bc5d98649d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -61,7 +61,7 @@ public: const lldb_private::RegisterValue ®_value); private: - uint32_t m_gpr[17]; + uint32_t m_gpr[17] = {0}; struct _sd_regs { uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index d4cb726fc7e5..a1a93c0b5a5f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -8,7 +8,7 @@ #include "EmulateInstructionMIPS.h" -#include <stdlib.h> +#include <cstdlib> #include "lldb/Core/Address.h" #include "lldb/Core/Opcode.h" @@ -159,8 +159,8 @@ EmulateInstructionMIPS::EmulateInstructionMIPS( target->createMCSubtargetInfo(triple.getTriple(), cpu, features)); assert(m_asm_info.get() && m_subtype_info.get()); - m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(), - m_reg_info.get(), nullptr); + m_context = std::make_unique<llvm::MCContext>( + triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get()); assert(m_context.get()); m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context)); @@ -1018,8 +1018,9 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode, const size_t bytes_read = target->ReadMemory(next_addr, /* Address of next instruction */ - true, /* prefer_file_cache */ - buf, sizeof(uint32_t), error, &load_addr); + buf, sizeof(uint32_t), error, + false, /* force_live_memory */ + &load_addr); if (bytes_read == 0) return true; diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 4ccaf0de0758..6044d00c0cbf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -8,7 +8,7 @@ #include "EmulateInstructionMIPS64.h" -#include <stdlib.h> +#include <cstdlib> #include "lldb/Core/Address.h" #include "lldb/Core/Opcode.h" @@ -163,8 +163,8 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64( target->createMCSubtargetInfo(triple.getTriple(), cpu, features)); assert(m_asm_info.get() && m_subtype_info.get()); - m_context = std::make_unique<llvm::MCContext>(m_asm_info.get(), - m_reg_info.get(), nullptr); + m_context = std::make_unique<llvm::MCContext>( + triple, m_asm_info.get(), m_reg_info.get(), m_subtype_info.get()); assert(m_context.get()); m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context)); diff --git a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp index 5d97513c0be7..4e78c369c128 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp @@ -8,7 +8,7 @@ #include "EmulateInstructionPPC64.h" -#include <stdlib.h> +#include <cstdlib> #include "lldb/Core/PluginManager.h" #include "lldb/Symbol/UnwindPlan.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp index 99784bd3dbd1..9a88b343878c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -127,7 +127,7 @@ InstrumentationRuntimeMainThreadChecker::RetrieveReportData( StackFrameSP responsible_frame; for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) { StackFrameSP frame = thread_sp->GetStackFrameAtIndex(I); - Address addr = frame->GetFrameCodeAddress(); + Address addr = frame->GetFrameCodeAddressForSymbolication(); if (addr.GetModule() == runtime_module_sp) // Skip PCs from the runtime. continue; @@ -135,11 +135,6 @@ InstrumentationRuntimeMainThreadChecker::RetrieveReportData( if (!responsible_frame) responsible_frame = frame; - // First frame in stacktrace should point to a real PC, not return address. - if (I != 0 && trace->GetSize() == 0) { - addr.Slide(-1); - } - lldb::addr_t PC = addr.GetLoadAddress(&target); trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(PC))); } @@ -271,8 +266,11 @@ InstrumentationRuntimeMainThreadChecker::GetBacktracesFromExtendedStopInfo( info->GetObjectForDotSeparatedPath("tid"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; - HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs); - ThreadSP new_thread_sp(history_thread); + // We gather symbolication addresses above, so no need for HistoryThread to + // try to infer the call addresses. + bool pcs_are_call_addresses = true; + ThreadSP new_thread_sp = std::make_shared<HistoryThread>( + *process_sp, tid, PCs, pcs_are_call_addresses); // Save this in the Process' ExtendedThreadList so a strong pointer retains // the object diff --git a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp index b60eb53f3d4a..58bc38a551f0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -29,7 +29,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" -#include <ctype.h> +#include <cctype> #include <memory> @@ -150,8 +150,8 @@ StructuredData::ObjectSP InstrumentationRuntimeUBSan::RetrieveReportData( StructuredData::Array *trace = new StructuredData::Array(); auto trace_sp = StructuredData::ObjectSP(trace); for (unsigned I = 0; I < thread_sp->GetStackFrameCount(); ++I) { - const Address FCA = - thread_sp->GetStackFrameAtIndex(I)->GetFrameCodeAddress(); + const Address FCA = thread_sp->GetStackFrameAtIndex(I) + ->GetFrameCodeAddressForSymbolication(); if (FCA.GetModule() == runtime_module_sp) // Skip PCs from the runtime. continue; @@ -324,8 +324,11 @@ InstrumentationRuntimeUBSan::GetBacktracesFromExtendedStopInfo( info->GetObjectForDotSeparatedPath("tid"); tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; - HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs); - ThreadSP new_thread_sp(history_thread); + // We gather symbolication addresses above, so no need for HistoryThread to + // try to infer the call addresses. + bool pcs_are_call_addresses = true; + ThreadSP new_thread_sp = std::make_shared<HistoryThread>( + *process_sp, tid, PCs, pcs_are_call_addresses); std::string stop_reason_description = GetStopReasonDescription(info); new_thread_sp->SetName(stop_reason_description.c_str()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp index 35788a6445c2..1c498a2ddc11 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -74,14 +74,12 @@ public: const CompilerType reserved_type = clang_ast_context->GetBasicType(lldb::eBasicTypeInt); const char *const FuncPtr_name("__FuncPtr"); - const CompilerType FuncPtr_type = - clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type); m_block_struct_type = clang_ast_context->CreateStructForIdentifier( ConstString(), {{isa_name, isa_type}, {flags_name, flags_type}, {reserved_name, reserved_type}, - {FuncPtr_name, FuncPtr_type}}); + {FuncPtr_name, function_pointer_type}}); } ~BlockPointerSyntheticFrontEnd() override = default; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index d844498fd8a3..895fd55f499c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -59,6 +59,11 @@ lldb_private::ConstString CPlusPlusLanguage::GetPluginNameStatic() { return g_name; } +bool CPlusPlusLanguage::SymbolNameFitsToLanguage(Mangled mangled) const { + const char *mangled_name = mangled.GetMangledName().GetCString(); + return mangled_name && CPlusPlusLanguage::IsCPPMangledName(mangled_name); +} + // PluginInterface protocol lldb_private::ConstString CPlusPlusLanguage::GetPluginName() { @@ -1054,7 +1059,7 @@ CPlusPlusLanguage::GetHardcodedSummaries() { .SetSkipReferences(false), lldb_private::formatters::VectorTypeSummaryProvider, "vector_type pointer summary provider")); - if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) { + if (valobj.GetCompilerType().IsVectorType()) { if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) return formatter_sp; } @@ -1074,7 +1079,7 @@ CPlusPlusLanguage::GetHardcodedSummaries() { .SetSkipReferences(false), lldb_private::formatters::BlockPointerSummaryProvider, "block pointer summary provider")); - if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) { + if (valobj.GetCompilerType().IsBlockPointerType()) { return formatter_sp; } return nullptr; @@ -1104,7 +1109,7 @@ CPlusPlusLanguage::GetHardcodedSynthetics() { .SetNonCacheable(true), "vector_type synthetic children", lldb_private::formatters::VectorTypeSyntheticFrontEndCreator)); - if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) { + if (valobj.GetCompilerType().IsVectorType()) { if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) return formatter_sp; } @@ -1123,7 +1128,7 @@ CPlusPlusLanguage::GetHardcodedSynthetics() { .SetNonCacheable(true), "block pointer synthetic children", lldb_private::formatters::BlockPointerSyntheticFrontEndCreator)); - if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) { + if (valobj.GetCompilerType().IsBlockPointerType()) { return formatter_sp; } return nullptr; @@ -1147,7 +1152,7 @@ bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const { const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c", ".h", ".hh", ".hpp", ".hxx", ".h++"}; for (auto suffix : suffixes) { - if (file_path.endswith_lower(suffix)) + if (file_path.endswith_insensitive(suffix)) return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h index e2b5d2918753..9163be4807ec 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -28,8 +28,7 @@ public: class MethodName { public: MethodName() - : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers(), - m_parsed(false), m_parse_error(false) {} + : m_full(), m_basename(), m_context(), m_arguments(), m_qualifiers() {} MethodName(ConstString s) : m_full(s), m_basename(), m_context(), m_arguments(), m_qualifiers(), @@ -68,8 +67,8 @@ public: llvm::StringRef m_context; // Decl context: "lldb::SBTarget" llvm::StringRef m_arguments; // Arguments: "(unsigned int)" llvm::StringRef m_qualifiers; // Qualifiers: "const" - bool m_parsed; - bool m_parse_error; + bool m_parsed = false; + bool m_parse_error = false; }; CPlusPlusLanguage() = default; @@ -105,6 +104,8 @@ public: static lldb_private::ConstString GetPluginNameStatic(); + bool SymbolNameFitsToLanguage(Mangled mangled) const override; + static bool IsCPPMangledName(llvm::StringRef name); // Extract C++ context and identifier from a string using heuristic matching diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h index 6fe6b12725b0..426434c48608 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h @@ -69,7 +69,7 @@ private: size_t begin_index = 0; size_t end_index = 0; - Range() {} + Range() = default; Range(size_t begin, size_t end) : begin_index(begin), end_index(end) { assert(end >= begin); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 2b16ebe79daf..8eda422f3145 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -379,8 +379,7 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator( lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: LibcxxSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr), m_count_sp(), - m_weak_count_sp(), m_ptr_size(0), m_byte_order(lldb::eByteOrderInvalid) { + : SyntheticChildrenFrontEnd(*valobj_sp), m_cntrl(nullptr) { if (valobj_sp) Update(); } @@ -403,42 +402,23 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex( if (idx == 0) return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); - if (idx > 2) - return lldb::ValueObjectSP(); - if (idx == 1) { - if (!m_count_sp) { - ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName( - ConstString("__shared_owners_"), true)); - if (!shared_owners_sp) - return lldb::ValueObjectSP(); - uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); - DataExtractor data(&count, 8, m_byte_order, m_ptr_size); - m_count_sp = CreateValueObjectFromData( - "count", data, valobj_sp->GetExecutionContextRef(), - shared_owners_sp->GetCompilerType()); - } - return m_count_sp; - } else /* if (idx == 2) */ - { - if (!m_weak_count_sp) { - ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName( - ConstString("__shared_weak_owners_"), true)); - if (!shared_weak_owners_sp) - return lldb::ValueObjectSP(); - uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); - DataExtractor data(&count, 8, m_byte_order, m_ptr_size); - m_weak_count_sp = CreateValueObjectFromData( - "count", data, valobj_sp->GetExecutionContextRef(), - shared_weak_owners_sp->GetCompilerType()); + if (auto ptr_sp = + valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)) { + Status status; + auto value_sp = ptr_sp->Dereference(status); + if (status.Success()) { + auto value_type_sp = + valobj_sp->GetCompilerType().GetTypeTemplateArgument(0); + return value_sp->Cast(value_type_sp); + } } - return m_weak_count_sp; } + + return lldb::ValueObjectSP(); } bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() { - m_count_sp.reset(); - m_weak_count_sp.reset(); m_cntrl = nullptr; ValueObjectSP valobj_sp = m_backend.GetSP(); @@ -449,9 +429,6 @@ bool lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() { if (!target_sp) return false; - m_byte_order = target_sp->GetArchitecture().GetByteOrder(); - m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); - lldb::ValueObjectSP cntrl_sp( valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"), true)); @@ -469,10 +446,8 @@ size_t lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd:: GetIndexOfChildWithName(ConstString name) { if (name == "__ptr_") return 0; - if (name == "count") + if (name == "$$dereference$$") return 1; - if (name == "weak_count") - return 2; return UINT32_MAX; } @@ -488,7 +463,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator( lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: LibcxxUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) - : SyntheticChildrenFrontEnd(*valobj_sp), m_compressed_pair_sp() { + : SyntheticChildrenFrontEnd(*valobj_sp) { if (valobj_sp) Update(); } @@ -505,19 +480,27 @@ lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEndCreator( size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: CalculateNumChildren() { - return (m_compressed_pair_sp ? 1 : 0); + return (m_value_ptr_sp ? 1 : 0); } lldb::ValueObjectSP lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::GetChildAtIndex( size_t idx) { - if (!m_compressed_pair_sp) + if (!m_value_ptr_sp) return lldb::ValueObjectSP(); - if (idx != 0) - return lldb::ValueObjectSP(); + if (idx == 0) + return m_value_ptr_sp; - return m_compressed_pair_sp; + if (idx == 1) { + Status status; + auto value_sp = m_value_ptr_sp->Dereference(status); + if (status.Success()) { + return value_sp; + } + } + + return lldb::ValueObjectSP(); } bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { @@ -530,7 +513,7 @@ bool lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd::Update() { if (!ptr_sp) return false; - m_compressed_pair_sp = GetValueOfLibCXXCompressedPair(*ptr_sp); + m_value_ptr_sp = GetValueOfLibCXXCompressedPair(*ptr_sp); return false; } @@ -544,6 +527,8 @@ size_t lldb_private::formatters::LibcxxUniquePtrSyntheticFrontEnd:: GetIndexOfChildWithName(ConstString name) { if (name == "__value_") return 0; + if (name == "$$dereference$$") + return 1; return UINT32_MAX; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h index ea5a7c178178..99e206543197 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -105,10 +105,6 @@ public: private: ValueObject *m_cntrl; - lldb::ValueObjectSP m_count_sp; - lldb::ValueObjectSP m_weak_count_sp; - uint8_t m_ptr_size; - lldb::ByteOrder m_byte_order; }; class LibcxxUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd { @@ -128,7 +124,7 @@ public: ~LibcxxUniquePtrSyntheticFrontEnd() override; private: - lldb::ValueObjectSP m_compressed_pair_sp; + lldb::ValueObjectSP m_value_ptr_sp; }; SyntheticChildrenFrontEnd * diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp index 6de4637a6a4a..e5b868fc0fce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp @@ -85,7 +85,7 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) { 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)) { + if (m_first->GetCompilerType().IsArrayType(&type)) { llvm::Optional<uint64_t> bit_size = type.GetBitSize(ctx.GetBestExecutionContextScope()); if (!bit_size || *bit_size == 0) diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 0d5ae16a0b29..47c6634ed65e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -27,8 +27,7 @@ namespace { class ListEntry { public: ListEntry() = default; - ListEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} - ListEntry(const ListEntry &rhs) = default; + ListEntry(ValueObjectSP entry_sp) : m_entry_sp(std::move(entry_sp)) {} ListEntry(ValueObject *entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} @@ -73,9 +72,8 @@ private: class ListIterator { public: ListIterator() = default; - ListIterator(ListEntry entry) : m_entry(entry) {} - ListIterator(ValueObjectSP entry) : m_entry(entry) {} - ListIterator(const ListIterator &rhs) = default; + ListIterator(ListEntry entry) : m_entry(std::move(entry)) {} + ListIterator(ValueObjectSP entry) : m_entry(std::move(entry)) {} ListIterator(ValueObject *entry) : m_entry(entry) {} ValueObjectSP value() { return m_entry.GetEntry(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index 64a199e24e4a..25c2bfd9387b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -26,7 +26,6 @@ class MapEntry { public: MapEntry() = default; explicit MapEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} - MapEntry(const MapEntry &rhs) = default; explicit MapEntry(ValueObject *entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} @@ -86,9 +85,9 @@ class MapIterator { public: MapIterator() = default; MapIterator(MapEntry entry, size_t depth = 0) - : m_entry(entry), m_max_depth(depth), m_error(false) {} + : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {} MapIterator(ValueObjectSP entry, size_t depth = 0) - : m_entry(entry), m_max_depth(depth), m_error(false) {} + : m_entry(std::move(entry)), m_max_depth(depth), m_error(false) {} MapIterator(const MapIterator &rhs) : m_entry(rhs.m_entry), m_max_depth(rhs.m_max_depth), m_error(false) {} MapIterator(ValueObject *entry, size_t depth = 0) @@ -138,7 +137,7 @@ protected: } private: - MapEntry tree_min(MapEntry &&x) { + MapEntry tree_min(MapEntry x) { if (x.null()) return MapEntry(); MapEntry left(x.left()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp index 0b34b4e2fc89..79e864a2cbd5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp @@ -99,9 +99,17 @@ bool LibStdcppUniquePtrSyntheticFrontEnd::Update() { if (ptr_obj) m_ptr_obj = ptr_obj->Clone(ConstString("pointer")).get(); - ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); - if (del_obj) - m_del_obj = del_obj->Clone(ConstString("deleter")).get(); + // Add a 'deleter' child if there was a non-empty deleter type specified. + // + // The object might have size=1 in the TypeSystem but occupies no dedicated + // storage due to no_unique_address, so infer the actual size from the total + // size of the unique_ptr class. If sizeof(unique_ptr) == sizeof(void*) then + // the deleter is empty and should be hidden. + if (tuple_sp->GetByteSize() > ptr_obj->GetByteSize()) { + ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1); + if (del_obj) + m_del_obj = del_obj->Clone(ConstString("deleter")).get(); + } if (m_ptr_obj) { Status error; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp index d871d3470e70..1479f4f0c151 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/Cocoa.cpp @@ -351,7 +351,7 @@ static void NSNumber_FormatInt(ValueObject &valobj, Stream &stream, int value, } static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, - uint64_t value, lldb::LanguageType lang) { + int64_t value, lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:long"); std::string prefix, suffix; @@ -367,10 +367,10 @@ static void NSNumber_FormatLong(ValueObject &valobj, Stream &stream, } static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, - const llvm::APInt &value, - lldb::LanguageType lang) { + const llvm::APInt &value, + lldb::LanguageType lang) { static ConstString g_TypeHint("NSNumber:int128_t"); - + std::string prefix, suffix; if (Language *language = Language::FindPlugin(lang)) { if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, @@ -379,11 +379,11 @@ static void NSNumber_FormatInt128(ValueObject &valobj, Stream &stream, suffix.clear(); } } - + stream.PutCString(prefix.c_str()); const int radix = 10; const bool isSigned = true; - std::string str = value.toString(radix, isSigned); + std::string str = llvm::toString(value, radix, isSigned); stream.PutCString(str.c_str()); stream.PutCString(suffix.c_str()); } @@ -426,6 +426,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( if (!process_sp) return false; + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get(*process_sp); if (!runtime) @@ -456,9 +457,18 @@ bool lldb_private::formatters::NSNumberSummaryProvider( return NSDecimalNumberSummaryProvider(valobj, stream, options); if (class_name == "NSNumber" || class_name == "__NSCFNumber") { - uint64_t value = 0; + int64_t value = 0; uint64_t i_bits = 0; - if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) { + if (descriptor->GetTaggedPointerInfoSigned(&i_bits, &value)) { + // Check for "preserved" numbers. We still don't support them yet. + if (i_bits & 0x8) { + if (log) + log->Printf( + "Unsupported (preserved) NSNumber tagged pointer 0x%" PRIu64, + valobj_addr); + return false; + } + switch (i_bits) { case 0: NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); @@ -498,49 +508,66 @@ bool lldb_private::formatters::NSNumberSummaryProvider( f64 = 0x5, sint128 = 0x6 }; - + uint64_t data_location = valobj_addr + 2 * ptr_size; TypeCodes type_code; - + if (new_format) { - uint64_t cfinfoa = - process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, - ptr_size, 0, error); - + uint64_t cfinfoa = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + ptr_size, ptr_size, 0, error); + if (error.Fail()) return false; bool is_preserved_number = cfinfoa & 0x8; if (is_preserved_number) { - lldbassert(!static_cast<bool>("We should handle preserved numbers!")); + if (log) + log->Printf( + "Unsupported preserved NSNumber tagged pointer 0x%" PRIu64, + valobj_addr); return false; } type_code = static_cast<TypeCodes>(cfinfoa & 0x7); } else { - uint8_t data_type = - process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, - 0, error) & 0x1F; - + uint8_t data_type = process_sp->ReadUnsignedIntegerFromMemory( + valobj_addr + ptr_size, 1, 0, error) & + 0x1F; + if (error.Fail()) return false; - + switch (data_type) { - case 1: type_code = TypeCodes::sint8; break; - case 2: type_code = TypeCodes::sint16; break; - case 3: type_code = TypeCodes::sint32; break; - case 17: data_location += 8; LLVM_FALLTHROUGH; - case 4: type_code = TypeCodes::sint64; break; - case 5: type_code = TypeCodes::f32; break; - case 6: type_code = TypeCodes::f64; break; - default: return false; + case 1: + type_code = TypeCodes::sint8; + break; + case 2: + type_code = TypeCodes::sint16; + break; + case 3: + type_code = TypeCodes::sint32; + break; + case 17: + data_location += 8; + LLVM_FALLTHROUGH; + case 4: + type_code = TypeCodes::sint64; + break; + case 5: + type_code = TypeCodes::f32; + break; + case 6: + type_code = TypeCodes::f64; + break; + default: + return false; } } - + uint64_t value = 0; bool success = false; switch (type_code) { - case TypeCodes::sint8: + case TypeCodes::sint8: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error); if (error.Fail()) @@ -548,7 +575,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); success = true; break; - case TypeCodes::sint16: + case TypeCodes::sint16: value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error); if (error.Fail()) @@ -573,8 +600,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); success = true; break; - case TypeCodes::f32: - { + case TypeCodes::f32: { uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory( data_location, 4, 0, error); if (error.Fail()) @@ -585,8 +611,7 @@ bool lldb_private::formatters::NSNumberSummaryProvider( success = true; break; } - case TypeCodes::f64: - { + case TypeCodes::f64: { uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory( data_location, 8, 0, error); if (error.Fail()) @@ -600,16 +625,17 @@ bool lldb_private::formatters::NSNumberSummaryProvider( case TypeCodes::sint128: // internally, this is the same { uint64_t words[2]; - words[1] = process_sp->ReadUnsignedIntegerFromMemory( - data_location, 8, 0, error); + words[1] = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, + 0, error); if (error.Fail()) return false; - words[0] = process_sp->ReadUnsignedIntegerFromMemory( - data_location + 8, 8, 0, error); + words[0] = process_sp->ReadUnsignedIntegerFromMemory(data_location + 8, + 8, 0, error); if (error.Fail()) return false; llvm::APInt i128_value(128, words); - NSNumber_FormatInt128(valobj, stream, i128_value, options.GetLanguage()); + NSNumber_FormatInt128(valobj, stream, i128_value, + options.GetLanguage()); success = true; break; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp index efc80cc75557..a862da551813 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -13,7 +13,7 @@ #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" -#include <inttypes.h> +#include <cinttypes> using namespace lldb; using namespace lldb_private; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index afb9c6951f55..326f47a10660 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -410,6 +410,7 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( static const ConstString g_DictionaryM("__NSDictionaryM"); static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable"); + static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); static const ConstString g_Dictionary0("__NSDictionary0"); static const ConstString g_DictionaryCF("__CFDictionary"); @@ -427,7 +428,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider( return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); - } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) { + } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy + || class_name == g_DictionaryMFrozen) { AppleObjCRuntime *apple_runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime); Status error; @@ -509,6 +511,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( static const ConstString g_DictionaryM("__NSDictionaryM"); static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable"); + static const ConstString g_DictionaryMFrozen("__NSFrozenDictionaryM"); static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy"); static const ConstString g_Dictionary0("__NSDictionary0"); static const ConstString g_DictionaryCF("__CFDictionary"); @@ -520,7 +523,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator( if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); - } else if (class_name == g_DictionaryM) { + } else if (class_name == g_DictionaryM || class_name == g_DictionaryMFrozen) { if (runtime->GetFoundationVersion() >= 1437) { return (new Foundation1437::NSDictionaryMSyntheticFrontEnd(valobj_sp)); } else if (runtime->GetFoundationVersion() >= 1428) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp index a15b0f64954a..068bca9e7b94 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp @@ -209,14 +209,13 @@ protected: m_process = nullptr; } - InlinedIndexes() - : m_indexes(0), m_count(0), m_ptr_size(0), m_process(nullptr) {} + InlinedIndexes() {} private: - uint64_t m_indexes; - size_t m_count; - uint32_t m_ptr_size; - Process *m_process; + uint64_t m_indexes = 0; + size_t m_count = 0; + uint32_t m_ptr_size = 0; + Process *m_process = nullptr; // cfr. Foundation for the details of this code size_t _lengthForInlinePayload(uint32_t ptr_size) { @@ -271,10 +270,10 @@ protected: m_count = 0; } - OutsourcedIndexes() : m_indexes(nullptr), m_count(0) {} + OutsourcedIndexes() {} - ValueObject *m_indexes; - size_t m_count; + ValueObject *m_indexes = nullptr; + size_t m_count = 0; }; union { @@ -288,9 +287,9 @@ protected: m_outsourced.Clear(); } - Impl() : m_mode(Mode::Invalid) {} + Impl() {} - Mode m_mode; + Mode m_mode = Mode::Invalid; } m_impl; uint32_t m_ptr_size; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp index 4dbbe6fbddff..43ef7b694bbe 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/NSSet.cpp @@ -444,18 +444,12 @@ bool lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - if (valobj_sp->IsPointerType()) { - valobj_sp = valobj_sp->Dereference(error); - if (error.Fail() || !valobj_sp) - return false; - } - 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->GetAddressOf() + m_ptr_size; + uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; + Status error; if (m_ptr_size == 4) { m_data_32 = new DataDescriptor_32(); process_sp->ReadMemory(data_location, m_data_32, sizeof(DataDescriptor_32), @@ -728,18 +722,12 @@ lldb_private::formatters:: if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - Status error; - if (valobj_sp->IsPointerType()) { - valobj_sp = valobj_sp->Dereference(error); - if (error.Fail() || !valobj_sp) - return false; - } - 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->GetAddressOf() + m_ptr_size; + uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; + Status error; if (m_ptr_size == 4) { m_data_32 = new D32(); process_sp->ReadMemory(data_location, m_data_32, sizeof(D32), diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 29391daaab93..379c53432b7b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -225,14 +225,17 @@ ConstString ObjCLanguage::MethodName::GetFullNameWithoutCategory( return ConstString(); } -std::vector<ConstString> +std::vector<Language::MethodNameVariant> ObjCLanguage::GetMethodNameVariants(ConstString method_name) const { - std::vector<ConstString> variant_names; + std::vector<Language::MethodNameVariant> variant_names; ObjCLanguage::MethodName objc_method(method_name.GetCString(), false); if (!objc_method.IsValid(false)) { return variant_names; } + variant_names.emplace_back(objc_method.GetSelector(), + lldb::eFunctionNameTypeSelector); + const bool is_class_method = objc_method.GetType() == MethodName::eTypeClassMethod; const bool is_instance_method = @@ -242,31 +245,43 @@ ObjCLanguage::GetMethodNameVariants(ConstString method_name) const { if (is_class_method || is_instance_method) { if (name_sans_category) - variant_names.emplace_back(name_sans_category); + variant_names.emplace_back(name_sans_category, + lldb::eFunctionNameTypeFull); } else { StreamString strm; strm.Printf("+%s", objc_method.GetFullName().GetCString()); - variant_names.emplace_back(strm.GetString()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); strm.Clear(); strm.Printf("-%s", objc_method.GetFullName().GetCString()); - variant_names.emplace_back(strm.GetString()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); strm.Clear(); if (name_sans_category) { strm.Printf("+%s", name_sans_category.GetCString()); - variant_names.emplace_back(strm.GetString()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); strm.Clear(); strm.Printf("-%s", name_sans_category.GetCString()); - variant_names.emplace_back(strm.GetString()); + variant_names.emplace_back(ConstString(strm.GetString()), + lldb::eFunctionNameTypeFull); } } return variant_names; } +bool ObjCLanguage::SymbolNameFitsToLanguage(Mangled mangled) const { + ConstString demangled_name = mangled.GetDemangledName(); + if (!demangled_name) + return false; + return ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()); +} + static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) { if (!objc_category_sp) return; @@ -990,8 +1005,11 @@ std::unique_ptr<Language::TypeScavenger> ObjCLanguage::GetTypeScavenger() { bool result = false; if (auto *target = exe_scope->CalculateTarget().get()) { - if (auto *clang_modules_decl_vendor = - target->GetClangModulesDeclVendor()) { + auto *persistent_vars = llvm::cast<ClangPersistentVariables>( + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)); + if (std::shared_ptr<ClangModulesDeclVendor> clang_modules_decl_vendor = + persistent_vars->GetClangModulesDeclVendor()) { ConstString key_cs(key); auto types = clang_modules_decl_vendor->FindTypes( key_cs, /*max_matches*/ UINT32_MAX); @@ -1116,7 +1134,7 @@ bool ObjCLanguage::IsNilReference(ValueObject &valobj) { bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const { const auto suffixes = {".h", ".m", ".M"}; for (auto suffix : suffixes) { - if (file_path.endswith_lower(suffix)) + if (file_path.endswith_insensitive(suffix)) return true; } return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h index 02c15e86046b..691c51883c8a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -27,9 +27,7 @@ public: public: enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod }; - MethodName() - : m_full(), m_class(), m_category(), m_selector(), - m_type(eTypeUnspecified), m_category_is_valid(false) {} + MethodName() : m_full(), m_class(), m_category(), m_selector() {} MethodName(const char *name, bool strict) : m_full(), m_class(), m_category(), m_selector(), @@ -81,8 +79,8 @@ public: m_class_category; // Class with category: "NSString(my_additions)" ConstString m_category; // Category: "my_additions" ConstString m_selector; // Selector: "myStringWithCString:" - Type m_type; - bool m_category_is_valid; + Type m_type = eTypeUnspecified; + bool m_category_is_valid = false; }; ObjCLanguage() = default; @@ -102,9 +100,12 @@ public: // variant_names[1] => "-[NSString(my_additions) myStringWithCString:]" // variant_names[2] => "+[NSString myStringWithCString:]" // variant_names[3] => "-[NSString myStringWithCString:]" - std::vector<ConstString> + // Also returns the FunctionNameType of each possible name. + std::vector<Language::MethodNameVariant> GetMethodNameVariants(ConstString method_name) const override; + bool SymbolNameFitsToLanguage(Mangled mangled) const override; + lldb::TypeCategoryImplSP GetFormatters() override; std::vector<ConstString> diff --git a/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp index 0a4017eda434..359978553210 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp @@ -19,7 +19,7 @@ LLDB_PLUGIN_DEFINE(ObjCPlusPlusLanguage) bool ObjCPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const { const auto suffixes = {".h", ".mm"}; for (auto suffix : suffixes) { - if (file_path.endswith_lower(suffix)) + if (file_path.endswith_insensitive(suffix)) return true; } return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp index 24ab9cc5f238..bed2a98067e6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <string.h> +#include <cstring> #include <memory> @@ -322,6 +322,9 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo( } } + if (symbol == nullptr) + return optional_info; + // Case 1 or 3 if (scl.GetSize() >= 1) { optional_info = line_entry_helper(target, scl[0], symbol, @@ -397,8 +400,8 @@ CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread, // We create a ThreadPlan to keep stepping through using the address range // of the current function. ret_plan_sp = std::make_shared<ThreadPlanStepInRange>( - thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes, - eLazyBoolYes); + thread, range_of_curr_func, sc, nullptr, eOnlyThisThread, + eLazyBoolYes, eLazyBoolYes); return ret_plan_sp; } } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 6ea9751f563a..f5b587c51960 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -196,7 +196,7 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress( // class_type_or_name.Clear(); - value_type = Value::ValueType::eValueTypeScalar; + value_type = Value::ValueType::Scalar; // Only a pointer or reference type can have a different dynamic and static // type: diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index bdd5c29db848..405b8a6f16b7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -252,6 +252,7 @@ bool ClassDescriptorV2::method_list_t::Read(Process *process, } bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, + lldb::addr_t relative_selector_base_addr, bool is_small, bool has_direct_sel) { size_t ptr_size = process->GetAddressByteSize(); size_t size = GetSize(process, is_small); @@ -281,6 +282,8 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr, 0, error); if (!error.Success()) return false; + } else if (relative_selector_base_addr != LLDB_INVALID_ADDRESS) { + m_name_ptr = relative_selector_base_addr + nameref_offset; } m_types_ptr = addr + 4 + types_offset; m_imp_ptr = addr + 8 + imp_offset; @@ -389,14 +392,14 @@ bool ClassDescriptorV2::Describe( if (base_method_list->m_entsize != method_t::GetSize(process, is_small)) return false; - std::unique_ptr<method_t> method; - method = std::make_unique<method_t>(); - + std::unique_ptr<method_t> method = std::make_unique<method_t>(); + lldb::addr_t relative_selector_base_addr = + m_runtime.GetRelativeSelectorBaseAddr(); for (uint32_t i = 0, e = base_method_list->m_count; i < e; ++i) { method->Read(process, base_method_list->m_first_ptr + (i * base_method_list->m_entsize), - is_small, has_direct_selector); + relative_selector_base_addr, is_small, has_direct_selector); if (instance_method_func(method->m_name.c_str(), method->m_types.c_str())) break; @@ -514,8 +517,7 @@ uint64_t ClassDescriptorV2::GetInstanceSize() { return 0; } -ClassDescriptorV2::iVarsStorage::iVarsStorage() - : m_filled(false), m_ivars(), m_mutex() {} +ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_ivars(), m_mutex() {} size_t ClassDescriptorV2::iVarsStorage::size() { return m_ivars.size(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 9ef21c6e7208..7ba957940ae7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -41,6 +41,12 @@ public: return false; } + bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, + int64_t *value_bits = nullptr, + uint64_t *payload = nullptr) override { + return false; + } + uint64_t GetInstanceSize() override; ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; } @@ -71,16 +77,14 @@ private: static const uint32_t RW_REALIZED = (1 << 31); struct objc_class_t { - ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass. - ObjCLanguageRuntime::ObjCISA m_superclass; - lldb::addr_t m_cache_ptr; - lldb::addr_t m_vtable_ptr; - lldb::addr_t m_data_ptr; - uint8_t m_flags; + ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass. + ObjCLanguageRuntime::ObjCISA m_superclass = 0; + lldb::addr_t m_cache_ptr = 0; + lldb::addr_t m_vtable_ptr = 0; + lldb::addr_t m_data_ptr = 0; + uint8_t m_flags = 0; - objc_class_t() - : m_isa(0), m_superclass(0), m_cache_ptr(0), m_vtable_ptr(0), - m_data_ptr(0), m_flags(0) {} + objc_class_t() = default; void Clear() { m_isa = 0; @@ -162,7 +166,8 @@ private: + field_size; // IMP imp; } - bool Read(Process *process, lldb::addr_t addr, bool, bool); + bool Read(Process *process, lldb::addr_t addr, + lldb::addr_t relative_method_lists_base_addr, bool, bool); }; struct ivar_list_t { @@ -207,7 +212,7 @@ private: void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor); private: - bool m_filled; + bool m_filled = false; std::vector<iVarDescriptor> m_ivars; std::recursive_mutex m_mutex; }; @@ -253,7 +258,7 @@ public: ClassDescriptorV2Tagged( ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp, - uint64_t payload) { + uint64_t u_payload, int64_t s_payload) { if (!actual_class_sp) { m_valid = false; return; @@ -264,9 +269,10 @@ public: return; } m_valid = true; - m_payload = payload; + m_payload = u_payload; m_info_bits = (m_payload & 0x0FULL); m_value_bits = (m_payload & ~0x0FULL) >> 4; + m_value_bits_signed = (s_payload & ~0x0FLL) >> 4; } ~ClassDescriptorV2Tagged() override = default; @@ -308,6 +314,18 @@ public: return true; } + bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, + int64_t *value_bits = nullptr, + uint64_t *payload = nullptr) override { + if (info_bits) + *info_bits = GetInfoBits(); + if (value_bits) + *value_bits = GetValueBitsSigned(); + if (payload) + *payload = GetPayload(); + return true; + } + uint64_t GetInstanceSize() override { return (IsValid() ? m_pointer_size : 0); } @@ -319,6 +337,10 @@ public: // these calls are not part of any formal tagged pointers specification virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); } + virtual int64_t GetValueBitsSigned() { + return (IsValid() ? m_value_bits_signed : 0); + } + virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); } virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); } @@ -329,6 +351,7 @@ private: bool m_valid; uint64_t m_info_bits; uint64_t m_value_bits; + int64_t m_value_bits_signed; uint64_t m_payload; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index 7b331307c0f7..9bc40c16e5d0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -59,7 +59,7 @@ public: clang::DeclContext::lookup_result result = non_const_interface_decl->lookup(name); - return (result.size() != 0); + return (!result.empty()); } while (false); SetNoExternalVisibleDeclsForName(decl_ctx, name); @@ -555,7 +555,7 @@ uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append, if (!lookup_result.empty()) { if (clang::ObjCInterfaceDecl *result_iface_decl = - llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) { + llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) { if (log) { clang::QualType result_iface_type = ast_ctx.getObjCInterfaceType(result_iface_decl); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 973a5570c06e..88e86c51fe44 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -48,7 +48,7 @@ LLDB_PLUGIN_DEFINE(AppleObjCRuntime) char AppleObjCRuntime::ID = 0; -AppleObjCRuntime::~AppleObjCRuntime() {} +AppleObjCRuntime::~AppleObjCRuntime() = default; AppleObjCRuntime::AppleObjCRuntime(Process *process) : ObjCLanguageRuntime(process), m_read_objc_library(false), diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index b37e5a9a7bf9..98d0e9cf991b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -49,7 +49,7 @@ bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress( TypeAndOrName &class_type_or_name, Address &address, Value::ValueType &value_type) { class_type_or_name.Clear(); - value_type = Value::ValueType::eValueTypeScalar; + value_type = Value::ValueType::Scalar; if (CouldHaveDynamicValue(in_value)) { auto class_descriptor(GetClassDescriptor(in_value)); if (class_descriptor && class_descriptor->IsValid() && @@ -339,8 +339,6 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { if (!objc_module_sp) return; - uint32_t isa_count = 0; - lldb::addr_t hash_table_ptr = GetISAHashTablePointer(); if (hash_table_ptr != LLDB_INVALID_ADDRESS) { // Read the NXHashTable struct: @@ -383,8 +381,6 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { if (bucket_isa_count == 0) continue; - isa_count += bucket_isa_count; - ObjCISA isa; if (bucket_isa_count == 1) { // When we only have one entry in the bucket, the bucket data diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h index 4eb7d979394b..12ee2cc53639 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h @@ -64,6 +64,12 @@ public: return false; } + bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, + int64_t *value_bits = nullptr, + uint64_t *payload = nullptr) override { + return false; + } + uint64_t GetInstanceSize() override { return m_instance_size; } ObjCISA GetISA() override { return m_isa; } @@ -120,8 +126,7 @@ protected: class HashTableSignature { public: - HashTableSignature() - : m_count(0), m_num_buckets(0), m_buckets_ptr(LLDB_INVALID_ADDRESS) {} + HashTableSignature() = default; bool NeedsUpdate(uint32_t count, uint32_t num_buckets, lldb::addr_t buckets_ptr) { @@ -137,9 +142,9 @@ protected: } protected: - uint32_t m_count; - uint32_t m_num_buckets; - lldb::addr_t m_buckets_ptr; + uint32_t m_count = 0; + uint32_t m_num_buckets = 0; + lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS; }; lldb::addr_t GetISAHashTablePointer(); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index ee84ccd869fc..10512a97ad69 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stdint.h> +#include <cstdint> #include <memory> #include <string> @@ -39,6 +39,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/DynamicLoader.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" @@ -75,8 +76,7 @@ char AppleObjCRuntimeV2::ID = 0; static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info"; -// Testing using the new C++11 raw string literals. If this breaks GCC then we -// will need to revert to the code above... + static const char *g_get_dynamic_class_info_body = R"( extern "C" @@ -121,14 +121,20 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr if (grc) { const unsigned num_classes = grc->num_classes; + DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes); if (class_infos_ptr) { + const unsigned num_buckets_minus_one = grc->num_buckets_minus_one; + DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one); + const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); + DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos); + ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; BucketInfo *buckets = (BucketInfo *)grc->buckets; - + uint32_t idx = 0; - for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i) + for (unsigned i=0; i<=num_buckets_minus_one; ++i) { if (buckets[i].name_ptr != NX_MAPNOTAKEY) { @@ -140,6 +146,7 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr h = ((h << 5) + h) + c; class_infos[idx].hash = h; class_infos[idx].isa = buckets[i].isa; + DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr); } ++idx; } @@ -157,6 +164,75 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr )"; +static const char *g_get_dynamic_class_info2_name = + "__lldb_apple_objc_v2_get_dynamic_class_info2"; + +static const char *g_get_dynamic_class_info2_body = R"( + +extern "C" { + int printf(const char * format, ...); + void free(void *ptr); + Class* objc_copyRealizedClassList_nolock(unsigned int *outCount); + const char* objc_debug_class_getNameRaw(Class cls); +} + +#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) + +struct ClassInfo +{ + Class isa; + uint32_t hash; +} __attribute__((__packed__)); + +uint32_t +__lldb_apple_objc_v2_get_dynamic_class_info2(void *gdb_objc_realized_classes_ptr, + void *class_infos_ptr, + uint32_t class_infos_byte_size, + uint32_t should_log) +{ + DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); + DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size); + + const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); + DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos); + + ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; + + uint32_t count = 0; + Class* realized_class_list = objc_copyRealizedClassList_nolock(&count); + DEBUG_PRINTF ("count = %u\n", count); + + uint32_t idx = 0; + for (uint32_t i=0; i<=count; ++i) + { + if (idx < max_class_infos) + { + Class isa = realized_class_list[i]; + const char *name_ptr = objc_debug_class_getNameRaw(isa); + if (name_ptr == NULL) + continue; + const char *s = name_ptr; + uint32_t h = 5381; + for (unsigned char c = *s; c; c = *++s) + h = ((h << 5) + h) + c; + class_infos[idx].hash = h; + class_infos[idx].isa = isa; + DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr); + } + idx++; + } + + if (idx < max_class_infos) + { + class_infos[idx].isa = NULL; + class_infos[idx].hash = 0; + } + + free(realized_class_list); + return count; +} +)"; + // We'll substitute in class_getName or class_getNameRaw depending // on which is present. static const char *g_shared_cache_class_name_funcptr = R"( @@ -169,8 +245,7 @@ extern "C" static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info"; -// Testing using the new C++11 raw string literals. If this breaks GCC then we -// will need to revert to the code above... + static const char *g_get_shared_cache_class_info_body = R"( extern "C" @@ -188,6 +263,12 @@ struct objc_classheader_t { int32_t hiOffset; }; +struct objc_classheader_v16_t { + uint64_t isDuplicate : 1, + objectCacheOffset : 47, // Offset from the shared cache base + dylibObjCIndex : 16; +}; + struct objc_clsopt_t { uint32_t capacity; uint32_t occupied; @@ -205,6 +286,22 @@ struct objc_clsopt_t { // objc_classheader_t duplicateOffsets[duplicateCount]; }; +struct objc_clsopt_v16_t { + uint32_t version; + uint32_t capacity; + uint32_t occupied; + uint32_t shift; + uint32_t mask; + uint64_t salt; + uint32_t scramble[256]; + uint8_t tab[0]; // tab[mask+1] + // uint8_t checkbytes[capacity]; + // int32_t offset[capacity]; + // objc_classheader_t clsOffsets[capacity]; + // uint32_t duplicateCount; + // objc_classheader_t duplicateOffsets[duplicateCount]; +}; + struct objc_opt_t { uint32_t version; int32_t selopt_offset; @@ -220,6 +317,20 @@ struct objc_opt_v14_t { int32_t clsopt_offset; }; +struct objc_opt_v16_t { + uint32_t version; + uint32_t flags; + int32_t selopt_offset; + int32_t headeropt_ro_offset; + int32_t unused_clsopt_offset; + int32_t unused_protocolopt_offset; + int32_t headeropt_rw_offset; + int32_t unused_protocolopt2_offset; + int32_t largeSharedCachesClassOffset; + int32_t largeSharedCachesProtocolOffset; + uint64_t relativeMethodSelectorBaseAddressCacheOffset; +}; + struct ClassInfo { Class isa; @@ -228,20 +339,33 @@ struct ClassInfo uint32_t __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, + void *shared_cache_base_ptr, void *class_infos_ptr, + uint64_t *relative_selector_offset, uint32_t class_infos_byte_size, uint32_t should_log) { + *relative_selector_offset = 0; uint32_t idx = 0; DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr); + DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr); DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo))); if (objc_opt_ro_ptr) { const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr; const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr; - const bool is_v14_format = objc_opt->version >= 14; - if (is_v14_format) + const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr; + if (objc_opt->version >= 16) + { + *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset; + DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version); + DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags); + DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset); + DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset); + DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset); + } + else if (objc_opt->version >= 14) { DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version); DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags); @@ -256,10 +380,126 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset); DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset); } - if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15) + + if (objc_opt->version == 16) + { + const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset); + const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); + + DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos); + + ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; + + const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1]; + const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity); + const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity); + + DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity); + DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask); + DEBUG_PRINTF ("classOffsets = %p\n", classOffsets); + + for (uint32_t i=0; i<clsopt->capacity; ++i) + { + const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset; + DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset); + + if (classOffsets[i].isDuplicate) { + DEBUG_PRINTF("isDuplicate = true\n"); + continue; // duplicate + } + + if (objectCacheOffset == 0) { + DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n"); + continue; // invalid offset + } + + if (class_infos && idx < max_class_infos) + { + class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset); + + // Lookup the class name. + const char *name = class_name_lookup_func(class_infos[idx].isa); + DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); + + // Hash the class name so we don't have to read it. + const char *s = name; + uint32_t h = 5381; + for (unsigned char c = *s; c; c = *++s) + { + // class_getName demangles swift names and the hash must + // be calculated on the mangled name. hash==0 means lldb + // will fetch the mangled name and compute the hash in + // ParseClassInfoArray. + if (c == '.') + { + h = 0; + break; + } + h = ((h << 5) + h) + c; + } + class_infos[idx].hash = h; + } + else + { + DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n"); + } + ++idx; + } + + const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity]; + const uint32_t duplicate_count = *duplicate_count_ptr; + const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]); + + DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count); + DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets); + + for (uint32_t i=0; i<duplicate_count; ++i) + { + const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset; + DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset); + + if (classOffsets[i].isDuplicate) { + DEBUG_PRINTF("isDuplicate = true\n"); + continue; // duplicate + } + + if (objectCacheOffset == 0) { + DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n"); + continue; // invalid offset + } + + if (class_infos && idx < max_class_infos) + { + class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset); + + // Lookup the class name. + const char *name = class_name_lookup_func(class_infos[idx].isa); + DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); + + // Hash the class name so we don't have to read it. + const char *s = name; + uint32_t h = 5381; + for (unsigned char c = *s; c; c = *++s) + { + // class_getName demangles swift names and the hash must + // be calculated on the mangled name. hash==0 means lldb + // will fetch the mangled name and compute the hash in + // ParseClassInfoArray. + if (c == '.') + { + h = 0; + break; + } + h = ((h << 5) + h) + c; + } + class_infos[idx].hash = h; + } + } + } + else if (objc_opt->version >= 12 && objc_opt->version <= 15) { const objc_clsopt_t* clsopt = NULL; - if (is_v14_format) + if (objc_opt->version >= 14) clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset); else clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset); @@ -291,7 +531,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF("clsOffset == invalidEntryOffset\n"); continue; // invalid offset } - + if (class_infos && idx < max_class_infos) { class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); @@ -321,7 +561,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, } ++idx; } - + const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity]; const uint32_t duplicate_count = *duplicate_count_ptr; const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]); @@ -334,7 +574,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, continue; // duplicate else if (clsOffset == invalidEntryOffset) continue; // invalid offset - + if (class_infos && idx < max_class_infos) { class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); @@ -353,7 +593,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, { h = 0; break; - } + } h = ((h << 5) + h) + c; } class_infos[idx].hash = h; @@ -380,55 +620,57 @@ ExtractRuntimeGlobalSymbol(Process *process, ConstString name, error.SetErrorString("no process"); return default_value; } + if (!module_sp) { error.SetErrorString("no module"); return default_value; } + if (!byte_size) byte_size = process->GetAddressByteSize(); const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData); - if (symbol && symbol->ValueIsAddress()) { - lldb::addr_t symbol_load_addr = - symbol->GetAddressRef().GetLoadAddress(&process->GetTarget()); - if (symbol_load_addr != LLDB_INVALID_ADDRESS) { - if (read_value) - return process->ReadUnsignedIntegerFromMemory( - symbol_load_addr, byte_size, default_value, error); - else - return symbol_load_addr; - } else { - error.SetErrorString("symbol address invalid"); - return default_value; - } - } else { + + if (!symbol || !symbol->ValueIsAddress()) { error.SetErrorString("no symbol"); return default_value; } + + lldb::addr_t symbol_load_addr = + symbol->GetAddressRef().GetLoadAddress(&process->GetTarget()); + if (symbol_load_addr == LLDB_INVALID_ADDRESS) { + error.SetErrorString("symbol address invalid"); + return default_value; + } + + if (read_value) + return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, + default_value, error); + return symbol_load_addr; } static void RegisterObjCExceptionRecognizer(Process *process); AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, const ModuleSP &objc_module_sp) - : AppleObjCRuntime(process), m_get_class_info_code(), - m_get_class_info_args(LLDB_INVALID_ADDRESS), - m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(), - m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS), - m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_up(), + : AppleObjCRuntime(process), m_objc_module_sp(objc_module_sp), + m_dynamic_class_info_extractor(*this), + m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(), m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS), - m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(), - m_has_object_getClass(false), m_loaded_objc_opt(false), - m_non_pointer_isa_cache_up( - NonPointerISACache::CreateInstance(*this, objc_module_sp)), + m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), + m_relative_selector_base(LLDB_INVALID_ADDRESS), m_hash_signature(), + m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false), + m_loaded_objc_opt(false), m_non_pointer_isa_cache_up(), m_tagged_pointer_vendor_up( TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)), m_encoding_to_type_sp(), m_noclasses_warning_emitted(false), - m_CFBoolean_values() { + m_CFBoolean_values(), m_realized_class_generation_count(0) { static const ConstString g_gdb_object_getClass("gdb_object_getClass"); - m_has_object_getClass = - (objc_module_sp->FindFirstSymbolWithNameAndType( - g_gdb_object_getClass, eSymbolTypeCode) != nullptr); + m_has_object_getClass = HasSymbol(g_gdb_object_getClass); + static const ConstString g_objc_copyRealizedClassList( + "_ZL33objc_copyRealizedClassList_nolockPj"); + m_has_objc_copyRealizedClassList = HasSymbol(g_objc_copyRealizedClassList); + RegisterObjCExceptionRecognizer(process); } @@ -451,7 +693,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress( assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get()); class_type_or_name.Clear(); - value_type = Value::ValueType::eValueTypeScalar; + value_type = Value::ValueType::Scalar; // Make sure we can have a dynamic value before starting... if (CouldHaveDynamicValue(in_value)) { @@ -498,15 +740,21 @@ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process, if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V2) return new AppleObjCRuntimeV2(process, objc_module_sp); - else - return nullptr; - } else return nullptr; + } + return nullptr; } static constexpr OptionDefinition g_objc_classtable_dump_options[] = { - {LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, - nullptr, {}, 0, eArgTypeNone, + {LLDB_OPT_SET_ALL, + false, + "verbose", + 'v', + OptionParser::eNoArgument, + nullptr, + {}, + 0, + eArgTypeNone, "Print ivar and method information in detail"}}; class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed { @@ -548,12 +796,13 @@ public: }; CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "dump", "Dump information on Objective-C classes " - "known to the current process.", - "language objc class-table dump", - eCommandRequiresProcess | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused), + : CommandObjectParsed(interpreter, "dump", + "Dump information on Objective-C classes " + "known to the current process.", + "language objc class-table dump", + eCommandRequiresProcess | + eCommandProcessMustBeLaunched | + eCommandProcessMustBePaused), m_options() { CommandArgumentEntry arg; CommandArgumentData index_arg; @@ -581,8 +830,8 @@ protected: case 0: break; case 1: { - regex_up = std::make_unique<RegularExpression>( - llvm::StringRef::withNullAsEmpty(command.GetArgumentAtIndex(0))); + regex_up = + std::make_unique<RegularExpression>(command.GetArgumentAtIndex(0)); if (!regex_up->IsValid()) { result.AppendError( "invalid argument - please provide a valid regular expression"); @@ -632,6 +881,7 @@ protected: ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"), ivar.m_size, ivar.m_offset); } + iterator->second->Describe( nullptr, [&std_out](const char *name, const char *type) -> bool { @@ -655,11 +905,10 @@ protected: } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); return true; - } else { - result.AppendError("current process has no Objective-C runtime loaded"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; } + result.AppendError("current process has no Objective-C runtime loaded"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; } CommandOptions m_options; @@ -741,11 +990,10 @@ protected: } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); return true; - } else { - result.AppendError("current process has no Objective-C runtime loaded"); - result.SetStatus(lldb::eReturnStatusFailed); - return false; } + result.AppendError("current process has no Objective-C runtime loaded"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; } }; @@ -951,11 +1199,7 @@ bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) { class RemoteNXMapTable { public: - RemoteNXMapTable() - : m_count(0), m_num_buckets_minus_one(0), - m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr), - m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS), - m_map_pair_size(0), m_invalid_key(0) {} + RemoteNXMapTable() : m_end_iterator(*this, -1) {} void Dump() { printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr); @@ -1129,18 +1373,17 @@ public: private: // contents of _NXMapTable struct - uint32_t m_count; - uint32_t m_num_buckets_minus_one; - lldb::addr_t m_buckets_ptr; - lldb_private::Process *m_process; + uint32_t m_count = 0; + uint32_t m_num_buckets_minus_one = 0; + lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS; + lldb_private::Process *m_process = nullptr; const_iterator m_end_iterator; - lldb::addr_t m_load_addr; - size_t m_map_pair_size; - lldb::addr_t m_invalid_key; + lldb::addr_t m_load_addr = LLDB_INVALID_ADDRESS; + size_t m_map_pair_size = 0; + lldb::addr_t m_invalid_key = 0; }; -AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() - : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {} +AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default; void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature( const RemoteNXMapTable &hash_table) { @@ -1171,8 +1414,8 @@ bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate( ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) { ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp; - if (m_non_pointer_isa_cache_up) - class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa); + if (auto *non_pointer_isa_cache = GetNonPointerIsaCache()) + class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa); if (!class_descriptor_sp) class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa); return class_descriptor_sp; @@ -1214,11 +1457,9 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) { objc_class_sp = GetClassDescriptorFromISA(isa); if (isa && !objc_class_sp) { - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | - LIBLLDB_LOG_TYPES)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); LLDB_LOGF(log, - "0x%" PRIx64 - ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " + "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " "not in class descriptor cache 0x%" PRIx64, isa_pointer, isa); } @@ -1229,28 +1470,29 @@ lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() { if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS) return m_tagged_pointer_obfuscator; - Process *process = GetProcess(); ModuleSP objc_module_sp(GetObjCModule()); if (!objc_module_sp) return LLDB_INVALID_ADDRESS; - static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator"); + static ConstString g_gdb_objc_obfuscator( + "objc_debug_taggedpointer_obfuscator"); const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType( - g_gdb_objc_obfuscator, lldb::eSymbolTypeAny); + g_gdb_objc_obfuscator, lldb::eSymbolTypeAny); if (symbol) { lldb::addr_t g_gdb_obj_obfuscator_ptr = - symbol->GetLoadAddress(&process->GetTarget()); + symbol->GetLoadAddress(&process->GetTarget()); if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) { Status error; - m_tagged_pointer_obfuscator = process->ReadPointerFromMemory( - g_gdb_obj_obfuscator_ptr, error); + m_tagged_pointer_obfuscator = + process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error); } } - // If we don't have a correct value at this point, there must be no obfuscation. + // If we don't have a correct value at this point, there must be no + // obfuscation. if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS) m_tagged_pointer_obfuscator = 0; @@ -1284,11 +1526,212 @@ lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() { return m_isa_hash_table_ptr; } +std::unique_ptr<UtilityFunction> +AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl( + ExecutionContext &exe_ctx, std::string code, std::string name) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); + + LLDB_LOG(log, "Creating utility function {0}", name); + + TypeSystemClang *ast = + ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); + if (!ast) + return {}; + + auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( + std::move(code), std::move(name), eLanguageTypeC, exe_ctx); + if (!utility_fn_or_error) { + LLDB_LOG_ERROR( + log, utility_fn_or_error.takeError(), + "Failed to get utility function for implementation lookup: {0}"); + return {}; + } + + // Make some types for our arguments. + CompilerType clang_uint32_t_type = + ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + CompilerType clang_void_pointer_type = + ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + + // Make the runner function for our implementation utility function. + ValueList arguments; + Value value; + value.SetValueType(Value::ValueType::Scalar); + value.SetCompilerType(clang_void_pointer_type); + arguments.PushValue(value); + arguments.PushValue(value); + value.SetValueType(Value::ValueType::Scalar); + value.SetCompilerType(clang_uint32_t_type); + arguments.PushValue(value); + arguments.PushValue(value); + + std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error); + + Status error; + utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments, + exe_ctx.GetThreadSP(), error); + + if (error.Fail()) { + LLDB_LOG(log, + "Failed to make function caller for implementation lookup: {0}.", + error.AsCString()); + return {}; + } + + return utility_fn; +} + +UtilityFunction * +AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunction( + ExecutionContext &exe_ctx, Helper helper) { + switch (helper) { + case gdb_objc_realized_classes: { + if (!m_gdb_objc_realized_classes_helper.utility_function) + m_gdb_objc_realized_classes_helper.utility_function = + GetClassInfoUtilityFunctionImpl(exe_ctx, + g_get_dynamic_class_info_body, + g_get_dynamic_class_info_name); + return m_gdb_objc_realized_classes_helper.utility_function.get(); + } + case objc_copyRealizedClassList: { + if (!m_objc_copyRealizedClassList_helper.utility_function) + m_objc_copyRealizedClassList_helper.utility_function = + GetClassInfoUtilityFunctionImpl(exe_ctx, + g_get_dynamic_class_info2_body, + g_get_dynamic_class_info2_name); + return m_objc_copyRealizedClassList_helper.utility_function.get(); + } + } + llvm_unreachable("Unexpected helper"); +} + +lldb::addr_t & +AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoArgs(Helper helper) { + switch (helper) { + case gdb_objc_realized_classes: + return m_gdb_objc_realized_classes_helper.args; + case objc_copyRealizedClassList: + return m_objc_copyRealizedClassList_helper.args; + } + llvm_unreachable("Unexpected helper"); +} + +AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper +AppleObjCRuntimeV2::DynamicClassInfoExtractor::ComputeHelper() const { + if (!m_runtime.m_has_objc_copyRealizedClassList) + return DynamicClassInfoExtractor::gdb_objc_realized_classes; + + if (Process *process = m_runtime.GetProcess()) { + if (DynamicLoader *loader = process->GetDynamicLoader()) { + if (loader->IsFullyInitialized()) + return DynamicClassInfoExtractor::objc_copyRealizedClassList; + } + } + + return DynamicClassInfoExtractor::gdb_objc_realized_classes; +} + +std::unique_ptr<UtilityFunction> +AppleObjCRuntimeV2::SharedCacheClassInfoExtractor:: + GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); + + LLDB_LOG(log, "Creating utility function {0}", + g_get_shared_cache_class_info_name); + + TypeSystemClang *ast = + ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); + if (!ast) + return {}; + + // If the inferior objc.dylib has the class_getNameRaw function, use that in + // our jitted expression. Else fall back to the old class_getName. + static ConstString g_class_getName_symbol_name("class_getName"); + static ConstString g_class_getNameRaw_symbol_name( + "objc_debug_class_getNameRaw"); + + ConstString class_name_getter_function_name = + m_runtime.HasSymbol(g_class_getNameRaw_symbol_name) + ? g_class_getNameRaw_symbol_name + : g_class_getName_symbol_name; + + // Substitute in the correct class_getName / class_getNameRaw function name, + // concatenate the two parts of our expression text. The format string has + // two %s's, so provide the name twice. + std::string shared_class_expression; + llvm::raw_string_ostream(shared_class_expression) + << llvm::format(g_shared_cache_class_name_funcptr, + class_name_getter_function_name.AsCString(), + class_name_getter_function_name.AsCString()); + + shared_class_expression += g_get_shared_cache_class_info_body; + + auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( + std::move(shared_class_expression), g_get_shared_cache_class_info_name, + eLanguageTypeC, exe_ctx); + + if (!utility_fn_or_error) { + LLDB_LOG_ERROR( + log, utility_fn_or_error.takeError(), + "Failed to get utility function for implementation lookup: {0}"); + return nullptr; + } + + // Make some types for our arguments. + CompilerType clang_uint32_t_type = + ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + CompilerType clang_void_pointer_type = + ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + CompilerType clang_uint64_t_pointer_type = + ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64) + .GetPointerType(); + + // Next make the function caller for our implementation utility function. + ValueList arguments; + Value value; + value.SetValueType(Value::ValueType::Scalar); + value.SetCompilerType(clang_void_pointer_type); + arguments.PushValue(value); + arguments.PushValue(value); + arguments.PushValue(value); + + value.SetValueType(Value::ValueType::Scalar); + value.SetCompilerType(clang_uint64_t_pointer_type); + arguments.PushValue(value); + + value.SetValueType(Value::ValueType::Scalar); + value.SetCompilerType(clang_uint32_t_type); + arguments.PushValue(value); + arguments.PushValue(value); + + std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error); + + Status error; + utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments, + exe_ctx.GetThreadSP(), error); + + if (error.Fail()) { + LLDB_LOG(log, + "Failed to make function caller for implementation lookup: {0}.", + error.AsCString()); + return {}; + } + + return utility_fn; +} + +UtilityFunction * +AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::GetClassInfoUtilityFunction( + ExecutionContext &exe_ctx) { + if (!m_utility_function) + m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx); + return m_utility_function.get(); +} + AppleObjCRuntimeV2::DescriptorMapUpdateResult -AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( +AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap( RemoteNXMapTable &hash_table) { - Process *process = GetProcess(); - + Process *process = m_runtime.GetProcess(); if (process == nullptr) return DescriptorMapUpdateResult::Fail(); @@ -1316,65 +1759,36 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( Status err; + // Compute which helper we're going to use for this update. + const DynamicClassInfoExtractor::Helper helper = ComputeHelper(); + // Read the total number of classes from the hash table - const uint32_t num_classes = hash_table.GetCount(); + const uint32_t num_classes = + helper == DynamicClassInfoExtractor::gdb_objc_realized_classes + ? hash_table.GetCount() + : m_runtime.m_realized_class_generation_count; if (num_classes == 0) { - LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes."); + LLDB_LOGF(log, "No dynamic classes found."); return DescriptorMapUpdateResult::Success(0); } - // Make some types for our arguments - CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); - CompilerType clang_void_pointer_type = - ast->GetBasicType(eBasicTypeVoid).GetPointerType(); - - ValueList arguments; - FunctionCaller *get_class_info_function = nullptr; - - if (!m_get_class_info_code) { - auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction( - g_get_dynamic_class_info_body, g_get_dynamic_class_info_name, - eLanguageTypeC, exe_ctx); - if (!utility_fn_or_error) { - LLDB_LOG_ERROR( - log, utility_fn_or_error.takeError(), - "Failed to get utility function for implementation lookup: {0}"); - return DescriptorMapUpdateResult::Fail(); - } - m_get_class_info_code = std::move(*utility_fn_or_error); - - // Next make the runner function for our implementation utility function. - Value value; - value.SetValueType(Value::eValueTypeScalar); - value.SetCompilerType(clang_void_pointer_type); - arguments.PushValue(value); - arguments.PushValue(value); - - value.SetValueType(Value::eValueTypeScalar); - value.SetCompilerType(clang_uint32_t_type); - arguments.PushValue(value); - arguments.PushValue(value); + UtilityFunction *get_class_info_code = + GetClassInfoUtilityFunction(exe_ctx, helper); + if (!get_class_info_code) { + // The callee will have already logged a useful error message. + return DescriptorMapUpdateResult::Fail(); + } - Status error; - get_class_info_function = m_get_class_info_code->MakeFunctionCaller( - clang_uint32_t_type, arguments, thread_sp, error); + FunctionCaller *get_class_info_function = + get_class_info_code->GetFunctionCaller(); - if (error.Fail()) { - LLDB_LOGF(log, - "Failed to make function caller for implementation lookup: %s.", - error.AsCString()); - return DescriptorMapUpdateResult::Fail(); - } - } else { - get_class_info_function = m_get_class_info_code->GetFunctionCaller(); - if (!get_class_info_function) { - LLDB_LOGF(log, "Failed to get implementation lookup function caller."); - return DescriptorMapUpdateResult::Fail(); - } - arguments = get_class_info_function->GetArgumentValues(); + if (!get_class_info_function) { + LLDB_LOGF(log, "Failed to get implementation lookup function caller."); + return DescriptorMapUpdateResult::Fail(); } + ValueList arguments = get_class_info_function->GetArgumentValues(); + DiagnosticManager diagnostics; const uint32_t class_info_byte_size = addr_size + 4; @@ -1390,18 +1804,18 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( return DescriptorMapUpdateResult::Fail(); } - std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex); + std::lock_guard<std::mutex> guard(m_mutex); // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; - + // Only dump the runtime classes from the expression evaluation if the log is // verbose: Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES); bool dump_log = type_log && type_log->GetVerbose(); - + arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0; bool success = false; @@ -1410,7 +1824,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( // Write our function arguments into the process so we can run our function if (get_class_info_function->WriteFunctionArguments( - exe_ctx, m_get_class_info_args, arguments, diagnostics)) { + exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(false); @@ -1419,8 +1833,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( options.SetTimeout(process->GetUtilityExpressionTimeout()); options.SetIsForUtilityExpr(true); + CompilerType clang_uint32_t_type = + ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + Value return_value; - return_value.SetValueType(Value::eValueTypeScalar); + return_value.SetValueType(Value::ValueType::Scalar); return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; @@ -1428,12 +1845,12 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( // Run the function ExpressionResults results = get_class_info_function->ExecuteFunction( - exe_ctx, &m_get_class_info_args, options, diagnostics, return_value); + exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value); if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos); + LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos); if (num_class_infos > 0) { // Read the ClassInfo structures DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); @@ -1443,7 +1860,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( DataExtractor class_infos_data(buffer.GetBytes(), buffer.GetByteSize(), process->GetByteOrder(), addr_size); - ParseClassInfoArray(class_infos_data, num_class_infos); + m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos); } } success = true; @@ -1507,15 +1924,16 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, ClassDescriptorSP descriptor_sp( new ClassDescriptorV2(*this, isa, nullptr)); - // The code in g_get_shared_cache_class_info_body sets the value of the hash - // to 0 to signal a demangled symbol. We use class_getName() in that code to - // find the class name, but this returns a demangled name for Swift symbols. - // For those symbols, recompute the hash here by reading their name from the - // runtime. + // The code in g_get_shared_cache_class_info_body sets the value of the + // hash to 0 to signal a demangled symbol. We use class_getName() in that + // code to find the class name, but this returns a demangled name for + // Swift symbols. For those symbols, recompute the hash here by reading + // their name from the runtime. if (name_hash) AddClass(isa, descriptor_sp, name_hash); else - AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr)); + AddClass(isa, descriptor_sp, + descriptor_sp->GetClassName().AsCString(nullptr)); num_parsed++; if (should_log) LLDB_LOGF(log, @@ -1531,10 +1949,20 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, return num_parsed; } -AppleObjCRuntimeV2::DescriptorMapUpdateResult -AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { - Process *process = GetProcess(); +bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) { + if (!m_objc_module_sp) + return false; + if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType( + Name, lldb::eSymbolTypeCode)) { + if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid()) + return true; + } + return false; +} +AppleObjCRuntimeV2::DescriptorMapUpdateResult +AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() { + Process *process = m_runtime.GetProcess(); if (process == nullptr) return DescriptorMapUpdateResult::Fail(); @@ -1562,103 +1990,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { uint32_t num_class_infos = 0; - const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); + const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress(); + const lldb::addr_t shared_cache_base_addr = + m_runtime.GetSharedCacheBaseAddress(); - if (objc_opt_ptr == LLDB_INVALID_ADDRESS) + if (objc_opt_ptr == LLDB_INVALID_ADDRESS || + shared_cache_base_addr == LLDB_INVALID_ADDRESS) return DescriptorMapUpdateResult::Fail(); const uint32_t num_classes = 128 * 1024; - // Make some types for our arguments - CompilerType clang_uint32_t_type = - ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); - CompilerType clang_void_pointer_type = - ast->GetBasicType(eBasicTypeVoid).GetPointerType(); - - ValueList arguments; - FunctionCaller *get_shared_cache_class_info_function = nullptr; - - if (!m_get_shared_cache_class_info_code) { - Status error; - - // If the inferior objc.dylib has the class_getNameRaw function, - // use that in our jitted expression. Else fall back to the old - // class_getName. - static ConstString g_class_getName_symbol_name("class_getName"); - static ConstString g_class_getNameRaw_symbol_name("objc_debug_class_getNameRaw"); - ConstString class_name_getter_function_name = g_class_getName_symbol_name; - - ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); - if (objc_runtime) { - for (lldb::ModuleSP mod_sp : process->GetTarget().GetImages().Modules()) { - if (objc_runtime->IsModuleObjCLibrary(mod_sp)) { - const Symbol *symbol = - mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name, - lldb::eSymbolTypeCode); - if (symbol && - (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) { - class_name_getter_function_name = g_class_getNameRaw_symbol_name; - } - } - } - } - - // Substitute in the correct class_getName / class_getNameRaw function name, - // concatenate the two parts of our expression text. The format string - // has two %s's, so provide the name twice. - std::string shared_class_expression; - llvm::raw_string_ostream(shared_class_expression) << llvm::format( - g_shared_cache_class_name_funcptr, - class_name_getter_function_name.AsCString(), - class_name_getter_function_name.AsCString()); - - shared_class_expression += g_get_shared_cache_class_info_body; - - auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( - std::move(shared_class_expression), g_get_shared_cache_class_info_name, - eLanguageTypeC, exe_ctx); - if (!utility_fn_or_error) { - LLDB_LOG_ERROR( - log, utility_fn_or_error.takeError(), - "Failed to get utility function for implementation lookup: {0}"); - return DescriptorMapUpdateResult::Fail(); - } - - m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error); + UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx); + FunctionCaller *get_shared_cache_class_info_function = + get_class_info_code->GetFunctionCaller(); - // Next make the function caller for our implementation utility function. - Value value; - value.SetValueType(Value::eValueTypeScalar); - value.SetCompilerType(clang_void_pointer_type); - arguments.PushValue(value); - arguments.PushValue(value); - - value.SetValueType(Value::eValueTypeScalar); - value.SetCompilerType(clang_uint32_t_type); - arguments.PushValue(value); - arguments.PushValue(value); - - get_shared_cache_class_info_function = - m_get_shared_cache_class_info_code->MakeFunctionCaller( - clang_uint32_t_type, arguments, thread_sp, error); - - if (get_shared_cache_class_info_function == nullptr) - return DescriptorMapUpdateResult::Fail(); - - } else { - get_shared_cache_class_info_function = - m_get_shared_cache_class_info_code->GetFunctionCaller(); - if (get_shared_cache_class_info_function == nullptr) - return DescriptorMapUpdateResult::Fail(); - arguments = get_shared_cache_class_info_function->GetArgumentValues(); + if (!get_shared_cache_class_info_function) { + LLDB_LOGF(log, "Failed to get implementation lookup function caller."); + return DescriptorMapUpdateResult::Fail(); } + ValueList arguments = + get_shared_cache_class_info_function->GetArgumentValues(); + DiagnosticManager diagnostics; const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory( class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); + const uint32_t relative_selector_offset_addr_size = 64; + lldb::addr_t relative_selector_offset_addr = + process->AllocateMemory(relative_selector_offset_addr_size, + ePermissionsReadable | ePermissionsWritable, err); if (class_infos_addr == LLDB_INVALID_ADDRESS) { LLDB_LOGF(log, @@ -1668,18 +2031,20 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { return DescriptorMapUpdateResult::Fail(); } - std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex); + std::lock_guard<std::mutex> guard(m_mutex); // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; - arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; - arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; + arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr; + arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr; + arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr; + arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size; // Only dump the runtime classes from the expression evaluation if the log is // verbose: Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES); bool dump_log = type_log && type_log->GetVerbose(); - - arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0; + + arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0; bool success = false; @@ -1687,8 +2052,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { // Write our function arguments into the process so we can run our function if (get_shared_cache_class_info_function->WriteFunctionArguments( - exe_ctx, m_get_shared_cache_class_info_args, arguments, - diagnostics)) { + exe_ctx, m_args, arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(false); @@ -1697,8 +2061,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { options.SetTimeout(process->GetUtilityExpressionTimeout()); options.SetIsForUtilityExpr(true); + CompilerType clang_uint32_t_type = + ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); + Value return_value; - return_value.SetValueType(Value::eValueTypeScalar); + return_value.SetValueType(Value::ValueType::Scalar); return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; @@ -1707,14 +2074,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { // Run the function ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction( - exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, - return_value); + exe_ctx, &m_args, options, diagnostics, return_value); if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in num_class_infos = return_value.GetScalar().ULong(); - LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n", - num_class_infos); + LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache", + num_class_infos); assert(num_class_infos <= num_classes); if (num_class_infos > 0) { if (num_class_infos > num_classes) { @@ -1725,16 +2091,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { success = true; } + // Read the relative selector offset. + DataBufferHeap relative_selector_offset_buffer(64, 0); + if (process->ReadMemory(relative_selector_offset_addr, + relative_selector_offset_buffer.GetBytes(), + relative_selector_offset_buffer.GetByteSize(), + err) == + relative_selector_offset_buffer.GetByteSize()) { + DataExtractor relative_selector_offset_data( + relative_selector_offset_buffer.GetBytes(), + relative_selector_offset_buffer.GetByteSize(), + process->GetByteOrder(), addr_size); + lldb::offset_t offset = 0; + uint64_t relative_selector_offset = + relative_selector_offset_data.GetU64(&offset); + if (relative_selector_offset > 0) { + // The offset is relative to the objc_opt struct. + m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr + + relative_selector_offset); + } + } + // Read the ClassInfo structures - DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); - if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), - buffer.GetByteSize(), - err) == buffer.GetByteSize()) { - DataExtractor class_infos_data(buffer.GetBytes(), - buffer.GetByteSize(), + DataBufferHeap class_infos_buffer( + num_class_infos * class_info_byte_size, 0); + if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(), + class_infos_buffer.GetByteSize(), + err) == class_infos_buffer.GetByteSize()) { + DataExtractor class_infos_data(class_infos_buffer.GetBytes(), + class_infos_buffer.GetByteSize(), process->GetByteOrder(), addr_size); - ParseClassInfoArray(class_infos_data, num_class_infos); + m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos); } } else { success = true; @@ -1758,42 +2146,6 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { return DescriptorMapUpdateResult(success, num_class_infos); } -bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( - RemoteNXMapTable &hash_table) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); - - Process *process = GetProcess(); - - if (process == nullptr) - return false; - - uint32_t num_map_table_isas = 0; - - ModuleSP objc_module_sp(GetObjCModule()); - - if (objc_module_sp) { - for (RemoteNXMapTable::element elt : hash_table) { - ++num_map_table_isas; - - if (ISAIsCached(elt.second)) - continue; - - ClassDescriptorSP descriptor_sp = ClassDescriptorSP( - new ClassDescriptorV2(*this, elt.second, elt.first.AsCString())); - - if (log && log->GetVerbose()) - LLDB_LOGF(log, - "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 - " (%s) from dynamic table to isa->descriptor cache", - elt.second, elt.first.AsCString()); - - AddClass(elt.second, descriptor_sp, elt.first.AsCString()); - } - } - - return num_map_table_isas > 0; -} - lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() { Process *process = GetProcess(); @@ -1827,6 +2179,19 @@ lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() { return LLDB_INVALID_ADDRESS; } +lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() { + StructuredData::ObjectSP info = m_process->GetSharedCacheInfo(); + if (!info) + return LLDB_INVALID_ADDRESS; + + StructuredData::Dictionary *info_dict = info->GetAsDictionary(); + if (!info_dict) + return LLDB_INVALID_ADDRESS; + + return info_dict->GetValueForKey("shared_cache_base_address") + ->GetIntegerValue(LLDB_INVALID_ADDRESS); +} + void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { LLDB_SCOPED_TIMER(); @@ -1842,14 +2207,19 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { // map, whether it was successful or not. m_isa_to_descriptor_stop_id = process->GetStopID(); - if (!m_hash_signature.NeedsUpdate(process, this, hash_table)) + // Ask the runtime is the realized class generation count changed. Unlike + // the hash table, this accounts for lazily named classes. + const bool class_count_changed = RealizedClassGenerationCountChanged(); + + if (!m_hash_signature.NeedsUpdate(process, this, hash_table) && + !class_count_changed) return; m_hash_signature.UpdateSignature(hash_table); - // Grab the dynamically loaded objc classes from the hash table in memory + // Grab the dynamically loaded Objective-C classes from memory. DescriptorMapUpdateResult dynamic_update_result = - UpdateISAToDescriptorMapDynamic(hash_table); + m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table); // Now get the objc classes that are baked into the Objective-C runtime in // the shared cache, but only once per process as this data never changes @@ -1865,7 +2235,7 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { const uint32_t num_classes_to_warn_at = 500; DescriptorMapUpdateResult shared_cache_update_result = - UpdateISAToDescriptorMapSharedCache(); + m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap(); LLDB_LOGF(log, "attempted to read objc class data - results: " @@ -1895,6 +2265,35 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { } } +bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() { + Process *process = GetProcess(); + if (!process) + return false; + + Status error; + uint64_t objc_debug_realized_class_generation_count = + ExtractRuntimeGlobalSymbol( + process, ConstString("objc_debug_realized_class_generation_count"), + GetObjCModule(), error); + if (error.Fail()) + return false; + + if (m_realized_class_generation_count == + objc_debug_realized_class_generation_count) + return false; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); + LLDB_LOG(log, + "objc_debug_realized_class_generation_count changed from {0} to {1}", + m_realized_class_generation_count, + objc_debug_realized_class_generation_count); + + m_realized_class_generation_count = + objc_debug_realized_class_generation_count; + + return true; +} + static bool DoesProcessHaveSharedCache(Process &process) { PlatformSP platform_sp = process.GetTarget().GetPlatform(); if (!platform_sp) @@ -1975,9 +2374,10 @@ lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { const ConstString ivar_name_cs(class_and_ivar.second); const char *ivar_name_cstr = ivar_name_cs.AsCString(); - auto ivar_func = [&ret, ivar_name_cstr]( - const char *name, const char *type, lldb::addr_t offset_addr, - uint64_t size) -> lldb::addr_t { + auto ivar_func = [&ret, + ivar_name_cstr](const char *name, const char *type, + lldb::addr_t offset_addr, + uint64_t size) -> lldb::addr_t { if (!strcmp(name, ivar_name_cstr)) { ret = offset_addr; return true; @@ -2279,7 +2679,6 @@ ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor( lldb::addr_t ptr) { ClassDescriptorSP actual_class_descriptor_sp; - uint64_t data_payload; uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); if (!IsPossibleTaggedPointer(unobfuscated)) @@ -2307,12 +2706,15 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor( m_cache[slot] = actual_class_descriptor_sp; } - data_payload = + uint64_t data_payload = (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift); - - return ClassDescriptorSP( - new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload)); + int64_t data_payload_signed = + ((int64_t)((int64_t)unobfuscated + << m_objc_debug_taggedpointer_payload_lshift) >> + m_objc_debug_taggedpointer_payload_rshift); + return ClassDescriptorSP(new ClassDescriptorV2Tagged( + actual_class_descriptor_sp, data_payload, data_payload_signed)); } AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended( @@ -2364,7 +2766,6 @@ ObjCLanguageRuntime::ClassDescriptorSP AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( lldb::addr_t ptr) { ClassDescriptorSP actual_class_descriptor_sp; - uint64_t data_payload; uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); if (!IsPossibleTaggedPointer(unobfuscated)) @@ -2395,12 +2796,16 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( m_ext_cache[slot] = actual_class_descriptor_sp; } - data_payload = - (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >> + uint64_t data_payload = (((uint64_t)unobfuscated + << m_objc_debug_taggedpointer_ext_payload_lshift) >> + m_objc_debug_taggedpointer_ext_payload_rshift); + int64_t data_payload_signed = + ((int64_t)((int64_t)unobfuscated + << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); - return ClassDescriptorSP( - new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload)); + return ClassDescriptorSP(new ClassDescriptorV2Tagged( + actual_class_descriptor_sp, data_payload, data_payload_signed)); } AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache( @@ -2552,8 +2957,8 @@ lldb_private::AppleObjCRuntime::ObjCISA AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) { ObjCISA ret = isa; - if (m_non_pointer_isa_cache_up) - m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret); + if (auto *non_pointer_isa_cache = GetNonPointerIsaCache()) + non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret); return ret; } @@ -2598,13 +3003,14 @@ void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, #pragma mark Frame recognizers class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { - public: +public: ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) { ThreadSP thread_sp = frame_sp->GetThread(); ProcessSP process_sp = thread_sp->GetProcess(); const lldb::ABISP &abi = process_sp->GetABI(); - if (!abi) return; + if (!abi) + return; TypeSystemClang *clang_ast_context = ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); @@ -2618,7 +3024,8 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { input_value.SetCompilerType(voidstar); args.PushValue(input_value); - if (!abi->GetArgumentValues(*thread_sp, args)) return; + if (!abi->GetArgumentValues(*thread_sp, args)) + return; addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong(); diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index c6fb6ea26b98..d0caa2969115 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -26,7 +26,6 @@ class AppleObjCRuntimeV2 : public AppleObjCRuntime { public: ~AppleObjCRuntimeV2() override = default; - // Static Functions static void Initialize(); static void Terminate(); @@ -46,7 +45,6 @@ public: return runtime->isA(&ID); } - // These are generic runtime functions: bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, TypeAndOrName &class_type_or_name, @@ -56,7 +54,6 @@ public: llvm::Expected<std::unique_ptr<UtilityFunction>> CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override; - // PluginInterface protocol ConstString GetPluginName() override; uint32_t GetPluginVersion() override; @@ -88,6 +85,15 @@ public: lldb::addr_t GetTaggedPointerObfuscator(); + /// Returns the base address for relative method list selector strings. + lldb::addr_t GetRelativeSelectorBaseAddr() { + return m_relative_selector_base; + } + + void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) { + m_relative_selector_base = relative_selector_base; + } + void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, lldb::addr_t &cf_false) override; @@ -105,8 +111,8 @@ public: protected: lldb::BreakpointResolverSP - CreateExceptionResolver(const lldb::BreakpointSP &bkpt, - bool catch_bp, bool throw_bp) override; + CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp, + bool throw_bp) override; private: class HashTableSignature { @@ -119,9 +125,9 @@ private: void UpdateSignature(const RemoteNXMapTable &hash_table); protected: - uint32_t m_count; - uint32_t m_num_buckets; - lldb::addr_t m_buckets_ptr; + uint32_t m_count = 0; + uint32_t m_num_buckets = 0; + lldb::addr_t m_buckets_ptr = 0; }; class NonPointerISACache { @@ -296,22 +302,99 @@ private: } }; + /// Abstraction to read the Objective-C class info. + class ClassInfoExtractor { + public: + ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {} + std::mutex &GetMutex() { return m_mutex; } + + protected: + /// The lifetime of this object is tied to that of the runtime. + AppleObjCRuntimeV2 &m_runtime; + std::mutex m_mutex; + }; + + /// We can read the class info from the Objective-C runtime using + /// gdb_objc_realized_classes or objc_copyRealizedClassList. The latter is + /// preferred because it includes lazily named classes, but it's not always + /// available or safe to call. + /// + /// We potentially need both for the same process, because we may need to use + /// gdb_objc_realized_classes until dyld is initialized and then switch over + /// to objc_copyRealizedClassList for lazily named classes. + class DynamicClassInfoExtractor : public ClassInfoExtractor { + public: + DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime) + : ClassInfoExtractor(runtime) {} + + DescriptorMapUpdateResult + UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table); + + private: + enum Helper { gdb_objc_realized_classes, objc_copyRealizedClassList }; + + /// Compute which helper to use. Prefer objc_copyRealizedClassList if it's + /// available and it's safe to call (i.e. dyld is fully initialized). Use + /// gdb_objc_realized_classes otherwise. + Helper ComputeHelper() const; + + UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx, + Helper helper); + lldb::addr_t &GetClassInfoArgs(Helper helper); + + std::unique_ptr<UtilityFunction> + GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, std::string code, + std::string name); + + /// Helper to read class info using the gdb_objc_realized_classes. + struct gdb_objc_realized_classes_helper { + std::unique_ptr<UtilityFunction> utility_function; + lldb::addr_t args = LLDB_INVALID_ADDRESS; + }; + + /// Helper to read class info using objc_copyRealizedClassList. + struct objc_copyRealizedClassList_helper { + std::unique_ptr<UtilityFunction> utility_function; + lldb::addr_t args = LLDB_INVALID_ADDRESS; + }; + + gdb_objc_realized_classes_helper m_gdb_objc_realized_classes_helper; + objc_copyRealizedClassList_helper m_objc_copyRealizedClassList_helper; + }; + + /// Abstraction to read the Objective-C class info from the shared cache. + class SharedCacheClassInfoExtractor : public ClassInfoExtractor { + public: + SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime) + : ClassInfoExtractor(runtime) {} + + DescriptorMapUpdateResult UpdateISAToDescriptorMap(); + + private: + UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx); + + std::unique_ptr<UtilityFunction> + GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx); + + std::unique_ptr<UtilityFunction> m_utility_function; + lldb::addr_t m_args = LLDB_INVALID_ADDRESS; + }; + AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp); ObjCISA GetPointerISA(ObjCISA isa); lldb::addr_t GetISAHashTablePointer(); - bool UpdateISAToDescriptorMapFromMemory(RemoteNXMapTable &hash_table); - - DescriptorMapUpdateResult - UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table); + /// Update the generation count of realized classes. This is not an exact + /// count but rather a value that is incremented when new classes are realized + /// or destroyed. Unlike the count in gdb_objc_realized_classes, it will + /// change when lazily named classes get realized. + bool RealizedClassGenerationCountChanged(); uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data, uint32_t num_class_infos); - DescriptorMapUpdateResult UpdateISAToDescriptorMapSharedCache(); - enum class SharedCacheWarningReason { eExpressionExecutionFailure, eNotEnoughClassesRead @@ -320,30 +403,40 @@ private: void WarnIfNoClassesCached(SharedCacheWarningReason reason); lldb::addr_t GetSharedCacheReadOnlyAddress(); + lldb::addr_t GetSharedCacheBaseAddress(); bool GetCFBooleanValuesIfNeeded(); + bool HasSymbol(ConstString Name); + + NonPointerISACache *GetNonPointerIsaCache() { + if (!m_non_pointer_isa_cache_up) + m_non_pointer_isa_cache_up.reset( + NonPointerISACache::CreateInstance(*this, m_objc_module_sp)); + return m_non_pointer_isa_cache_up.get(); + } + friend class ClassDescriptorV2; - std::unique_ptr<UtilityFunction> m_get_class_info_code; - lldb::addr_t m_get_class_info_args; - std::mutex m_get_class_info_args_mutex; + lldb::ModuleSP m_objc_module_sp; - std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code; - lldb::addr_t m_get_shared_cache_class_info_args; - std::mutex m_get_shared_cache_class_info_args_mutex; + DynamicClassInfoExtractor m_dynamic_class_info_extractor; + SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor; std::unique_ptr<DeclVendor> m_decl_vendor_up; lldb::addr_t m_tagged_pointer_obfuscator; lldb::addr_t m_isa_hash_table_ptr; + lldb::addr_t m_relative_selector_base; HashTableSignature m_hash_signature; bool m_has_object_getClass; + bool m_has_objc_copyRealizedClassList; bool m_loaded_objc_opt; std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up; std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up; EncodingToTypeSP m_encoding_to_type_sp; bool m_noclasses_warning_emitted; llvm::Optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values; + uint64_t m_realized_class_generation_count; }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index bcc1f6fd339f..aa6306bef8b9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -285,7 +285,7 @@ AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion( SetUpRegion(); } -AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() {} +AppleObjCTrampolineHandler::~AppleObjCTrampolineHandler() = default; void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() { // The header looks like: @@ -526,7 +526,7 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines( CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - input_value.SetValueType(Value::eValueTypeScalar); + input_value.SetValueType(Value::ValueType::Scalar); // input_value.SetContext (Value::eContextTypeClangType, // clang_void_ptr_type); input_value.SetCompilerType(clang_void_ptr_type); @@ -936,7 +936,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, Value void_ptr_value; CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - void_ptr_value.SetValueType(Value::eValueTypeScalar); + void_ptr_value.SetValueType(Value::ValueType::Scalar); // void_ptr_value.SetContext (Value::eContextTypeClangType, // clang_void_ptr_type); void_ptr_value.SetCompilerType(clang_void_ptr_type); @@ -1048,7 +1048,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, Value isa_value(*(argument_values.GetValueAtIndex(obj_index))); - isa_value.SetValueType(Value::eValueTypeLoadAddress); + isa_value.SetValueType(Value::ValueType::LoadAddress); isa_value.ResolveValue(&exe_ctx); if (isa_value.GetScalar().IsValid()) { isa_addr = isa_value.GetScalar().ULongLong(); @@ -1110,7 +1110,7 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, CompilerType clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize( lldb::eEncodingSint, 32); - flag_value.SetValueType(Value::eValueTypeScalar); + flag_value.SetValueType(Value::ValueType::Scalar); // flag_value.SetContext (Value::eContextTypeClangType, clang_int_type); flag_value.SetCompilerType(clang_int_type); @@ -1157,13 +1157,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done. dispatch_values.PushValue(flag_value); - // The step through code might have to fill in the cache, so it - // is not safe to run only one thread. So we override the - // stop_others value passed in to us here: - const bool trampoline_stop_others = false; ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughObjCTrampoline>( - thread, *this, dispatch_values, isa_addr, sel_addr, - trampoline_stop_others); + thread, *this, dispatch_values, isa_addr, sel_addr); if (log) { StreamString s; ret_plan_sp->GetDescription(&s, eDescriptionLevelFull); @@ -1182,13 +1177,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread, MsgsendMap::iterator pos; pos = m_opt_dispatch_map.find(curr_pc); if (pos != m_opt_dispatch_map.end()) { - const char *opt_name = g_opt_dispatch_names[(*pos).second]; - - bool trampoline_stop_others = false; - LazyBool step_in_should_stop = eLazyBoolCalculate; - ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch> ( - thread, *this, opt_name, trampoline_stop_others, step_in_should_stop); + ret_plan_sp = std::make_shared<AppleThreadPlanStepThroughDirectDispatch>( + thread, *this, opt_name); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index 27aebd8594df..546b500b4529 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -76,10 +76,7 @@ private: class VTableRegion { public: - VTableRegion() - : m_valid(false), m_owner(nullptr), - m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0), - m_code_end_addr(0), m_next_region(0) {} + VTableRegion() = default; VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); @@ -99,13 +96,13 @@ private: void Dump(Stream &s); - bool m_valid; - AppleObjCVTables *m_owner; - lldb::addr_t m_header_addr; - lldb::addr_t m_code_start_addr; - lldb::addr_t m_code_end_addr; + bool m_valid = false; + AppleObjCVTables *m_owner = nullptr; + lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t m_code_start_addr = 0; + lldb::addr_t m_code_end_addr = 0; std::vector<VTableDescriptor> m_descriptors; - lldb::addr_t m_next_region; + lldb::addr_t m_next_region = 0; }; public: diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index b19d3d90d4b7..7b0121503bc4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -59,7 +59,7 @@ uint32_t AppleObjCTypeEncodingParser::ReadNumber(StringLexer &type) { // "{CGRect=\"origin\"{CGPoint=\"x\"d\"y\"d}\"size\"{CGSize=\"width\"d\"height\"d}}" AppleObjCTypeEncodingParser::StructElement::StructElement() - : name(""), type(clang::QualType()), bitfield(0) {} + : name(""), type(clang::QualType()) {} AppleObjCTypeEncodingParser::StructElement AppleObjCTypeEncodingParser::ReadStructElement(TypeSystemClang &ast_ctx, diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h index 9a108967e1ab..6e533b591eca 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h @@ -29,7 +29,7 @@ private: struct StructElement { std::string name; clang::QualType type; - uint32_t bitfield; + uint32_t bitfield = 0; StructElement(); ~StructElement() = default; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 653e007c7b5f..1dc8034c537a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -30,19 +30,17 @@ using namespace lldb_private; AppleThreadPlanStepThroughObjCTrampoline:: AppleThreadPlanStepThroughObjCTrampoline( Thread &thread, AppleObjCTrampolineHandler &trampoline_handler, - ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr, - bool stop_others) + ValueList &input_values, lldb::addr_t isa_addr, lldb::addr_t sel_addr) : ThreadPlan(ThreadPlan::eKindGeneric, "MacOSX Step through ObjC Trampoline", thread, eVoteNoOpinion, eVoteNoOpinion), m_trampoline_handler(trampoline_handler), m_args_addr(LLDB_INVALID_ADDRESS), m_input_values(input_values), - m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr), - m_stop_others(stop_others) {} + m_isa_addr(isa_addr), m_sel_addr(sel_addr), m_impl_function(nullptr) {} // Destructor AppleThreadPlanStepThroughObjCTrampoline:: - ~AppleThreadPlanStepThroughObjCTrampoline() {} + ~AppleThreadPlanStepThroughObjCTrampoline() = default; void AppleThreadPlanStepThroughObjCTrampoline::DidPush() { // Setting up the memory space for the called function text might require @@ -66,7 +64,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller() { EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); - options.SetStopOthers(m_stop_others); + options.SetStopOthers(false); GetThread().CalculateExecutionContext(exc_ctx); m_func_sp = m_impl_function->GetThreadPlanToCallFunction( exc_ctx, m_args_addr, options, diagnostics); @@ -157,7 +155,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { const bool first_insn = true; const uint32_t frame_idx = 0; m_run_to_sp = GetThread().QueueThreadPlanForStepOutNoShouldStop( - abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion, + abort_other_plans, &sc, first_insn, false, eVoteNoOpinion, eVoteNoOpinion, frame_idx, status); if (m_run_to_sp && status.Success()) m_run_to_sp->SetPrivate(true); @@ -179,7 +177,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) { // Extract the target address from the value: m_run_to_sp = std::make_shared<ThreadPlanRunToAddress>( - GetThread(), target_so_addr, m_stop_others); + GetThread(), target_so_addr, false); PushPlan(m_run_to_sp); return false; } else if (GetThread().IsThreadPlanDone(m_run_to_sp.get())) { @@ -222,10 +220,9 @@ bool AppleThreadPlanStepThroughObjCTrampoline::WillStop() { return true; } AppleThreadPlanStepThroughDirectDispatch :: AppleThreadPlanStepThroughDirectDispatch( Thread &thread, AppleObjCTrampolineHandler &handler, - llvm::StringRef dispatch_func_name, bool stop_others, - LazyBool step_in_avoids_code_without_debug_info) - : ThreadPlanStepOut(thread, nullptr, true /* first instruction */, - stop_others, eVoteNoOpinion, eVoteNoOpinion, + llvm::StringRef dispatch_func_name) + : ThreadPlanStepOut(thread, nullptr, true /* first instruction */, false, + eVoteNoOpinion, eVoteNoOpinion, 0 /* Step out of zeroth frame */, eLazyBoolNo /* Our parent plan will decide this when we are done */ @@ -234,7 +231,7 @@ AppleThreadPlanStepThroughDirectDispatch :: false /* Don't gather the return value */), m_trampoline_handler(handler), m_dispatch_func_name(std::string(dispatch_func_name)), - m_at_msg_send(false), m_stop_others(stop_others) { + m_at_msg_send(false) { // Set breakpoints on the dispatch functions: auto bkpt_callback = [&] (lldb::addr_t addr, const AppleObjCTrampolineHandler @@ -249,20 +246,7 @@ AppleThreadPlanStepThroughDirectDispatch :: // We'll set the step-out plan in the DidPush so it gets queued in the right // order. - bool avoid_nodebug = true; - - switch (step_in_avoids_code_without_debug_info) { - case eLazyBoolYes: - avoid_nodebug = true; - break; - case eLazyBoolNo: - avoid_nodebug = false; - break; - case eLazyBoolCalculate: - avoid_nodebug = GetThread().GetStepInAvoidsNoDebug(); - break; - } - if (avoid_nodebug) + if (GetThread().GetStepInAvoidsNoDebug()) GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug); else GetFlags().Clear(ThreadPlanShouldStopHere::eStepInAvoidNoDebug); @@ -398,8 +382,8 @@ bool AppleThreadPlanStepThroughDirectDispatch::ShouldStop(Event *event_ptr) { // There's no way we could have gotten here without an ObjC language // runtime. assert(objc_runtime); - m_objc_step_through_sp - = objc_runtime->GetStepThroughTrampolinePlan(GetThread(), m_stop_others); + m_objc_step_through_sp = + objc_runtime->GetStepThroughTrampolinePlan(GetThread(), false); // If we failed to find the target for this dispatch, just keep going and // let the step out complete. if (!m_objc_step_through_sp) { diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h index 89aed89f1ab1..b5b45079094c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h @@ -24,8 +24,7 @@ class AppleThreadPlanStepThroughObjCTrampoline : public ThreadPlan { public: AppleThreadPlanStepThroughObjCTrampoline( Thread &thread, AppleObjCTrampolineHandler &trampoline_handler, - ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr, - bool stop_others); + ValueList &values, lldb::addr_t isa_addr, lldb::addr_t sel_addr); ~AppleThreadPlanStepThroughObjCTrampoline() override; @@ -39,7 +38,9 @@ public: bool ShouldStop(Event *event_ptr) override; - bool StopOthers() override { return m_stop_others; } + // The step through code might have to fill in the cache, so it is not safe + // to run only one thread. + bool StopOthers() override { return false; } // The base class MischiefManaged does some cleanup - so you have to call it // in your MischiefManaged derived class. @@ -69,15 +70,13 @@ private: FunctionCaller *m_impl_function; /// This is a pointer to a impl function that /// is owned by the client that pushes this /// plan. - bool m_stop_others; /// Whether we should stop other threads. }; class AppleThreadPlanStepThroughDirectDispatch: public ThreadPlanStepOut { public: - AppleThreadPlanStepThroughDirectDispatch( - Thread &thread, AppleObjCTrampolineHandler &handler, - llvm::StringRef dispatch_func_name, bool stop_others, - LazyBool step_in_avoids_code_without_debug_info); + AppleThreadPlanStepThroughDirectDispatch(Thread &thread, + AppleObjCTrampolineHandler &handler, + llvm::StringRef dispatch_func_name); ~AppleThreadPlanStepThroughDirectDispatch() override; @@ -85,7 +84,7 @@ public: bool ShouldStop(Event *event_ptr) override; - bool StopOthers() override { return m_stop_others; } + bool StopOthers() override { return false; } bool MischiefManaged() override; @@ -107,7 +106,6 @@ protected: std::vector<lldb::BreakpointSP> m_msgSend_bkpts; /// Breakpoints on the objc /// dispatch functions. bool m_at_msg_send; /// Are we currently handling an msg_send - bool m_stop_others; /// Whether we should stop other threads. }; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index 2ccf9b33f9d8..65bf3e6af626 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -32,7 +32,7 @@ using namespace lldb_private; char ObjCLanguageRuntime::ID = 0; // Destructor -ObjCLanguageRuntime::~ObjCLanguageRuntime() {} +ObjCLanguageRuntime::~ObjCLanguageRuntime() = default; ObjCLanguageRuntime::ObjCLanguageRuntime(Process *process) : LanguageRuntime(process), m_impl_cache(), @@ -305,7 +305,7 @@ ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name, return CompilerType(); } -ObjCLanguageRuntime::EncodingToType::~EncodingToType() {} +ObjCLanguageRuntime::EncodingToType::~EncodingToType() = default; ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() { return nullptr; @@ -363,7 +363,8 @@ void ObjCLanguageRuntime::ObjCExceptionPrecondition::AddClassName( m_class_names.insert(class_name); } -ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() {} +ObjCLanguageRuntime::ObjCExceptionPrecondition::ObjCExceptionPrecondition() = + default; bool ObjCLanguageRuntime::ObjCExceptionPrecondition::EvaluatePrecondition( StoppointCallbackContext &context) { diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h index 683eff777728..15fce04ea465 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h @@ -49,9 +49,7 @@ public: // implementations of the runtime, and more might come class ClassDescriptor { public: - ClassDescriptor() - : m_is_kvo(eLazyBoolCalculate), m_is_cf(eLazyBoolCalculate), - m_type_wp() {} + ClassDescriptor() : m_type_wp() {} virtual ~ClassDescriptor() = default; @@ -87,10 +85,20 @@ public: virtual bool IsValid() = 0; + /// There are two routines in the ObjC runtime that tagged pointer clients + /// can call to get the value from their tagged pointer, one that retrieves + /// it as an unsigned value and one a signed value. These two + /// GetTaggedPointerInfo methods mirror those two ObjC runtime calls. + /// @{ virtual bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr, uint64_t *value_bits = nullptr, uint64_t *payload = nullptr) = 0; + virtual bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr, + int64_t *value_bits = nullptr, + uint64_t *payload = nullptr) = 0; + /// @} + virtual uint64_t GetInstanceSize() = 0; // use to implement version-specific additional constraints on pointers @@ -135,8 +143,8 @@ public: bool check_version_specific = false) const; private: - LazyBool m_is_kvo; - LazyBool m_is_cf; + LazyBool m_is_kvo = eLazyBoolCalculate; + LazyBool m_is_cf = eLazyBoolCalculate; lldb::TypeWP m_type_wp; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp index 6858c7134d33..08a752eaa888 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp @@ -185,7 +185,7 @@ RSIRPasses::RSIRPasses(Process *process) { EarlyPasses->add(new RenderScriptRuntimeModulePass(process)); } -RSIRPasses::~RSIRPasses() {} +RSIRPasses::~RSIRPasses() = default; } // namespace lldb_renderscript } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index dd9312234d8b..10ff5aa72b52 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -61,7 +61,7 @@ namespace { template <typename type_t> class empirical_type { public: // Ctor. Contents is invalid when constructed. - empirical_type() : valid(false) {} + empirical_type() = default; // Return true and copy contents to out if valid, else return false. bool get(type_t &out) const { @@ -99,7 +99,7 @@ public: } protected: - bool valid; + bool valid = false; type_t data; }; @@ -2228,7 +2228,7 @@ bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc, return JITAllocationSize(alloc, frame_ptr); } -// Function attempts to set the type_name member of the paramaterised Element +// Function attempts to set the type_name member of the parameterised Element // object. This string should be the name of the struct type the Element // represents. We need this string for pretty printing the Element to users. void RenderScriptRuntime::FindStructTypeName(Element &elem, @@ -4087,9 +4087,7 @@ public: class CommandOptions : public Options { public: - CommandOptions() - : Options(), - m_kernel_types(RSReduceBreakpointResolver::eKernelTypeAll) {} + CommandOptions() : Options() {} ~CommandOptions() override = default; @@ -4175,7 +4173,7 @@ public: return true; } - int m_kernel_types; + int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll; llvm::StringRef m_reduce_name; RSCoordinate m_coord; bool m_have_coord; @@ -4189,7 +4187,6 @@ public: result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, " "and an optional kernel type list", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4203,7 +4200,6 @@ public: auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr; if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord, m_options.m_kernel_types)) { - result.SetStatus(eReturnStatusFailed); result.AppendError("Error: unable to place breakpoint on reduction"); return false; } @@ -4291,7 +4287,6 @@ public: result.AppendErrorWithFormat( "'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4304,7 +4299,6 @@ public: auto name = command.GetArgumentAtIndex(0); auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr; if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) { - result.SetStatus(eReturnStatusFailed); result.AppendErrorWithFormat( "Error: unable to set breakpoint on kernel '%s'", name); return false; @@ -4342,7 +4336,6 @@ public: if (argc != 1) { result.AppendErrorWithFormat( "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4361,7 +4354,6 @@ public: } else { result.AppendErrorWithFormat( "Argument must be either 'enable' or 'disable'"); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4568,7 +4560,6 @@ public: result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. " "As well as an optional -f argument", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4583,7 +4574,6 @@ public: if (!success) { result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4608,7 +4598,6 @@ public: std::string error = llvm::toString(file.takeError()); result.AppendErrorWithFormat("Couldn't open file '%s': %s", path.c_str(), error.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } } else @@ -4653,7 +4642,7 @@ public: class CommandOptions : public Options { public: - CommandOptions() : Options(), m_id(0) {} + CommandOptions() : Options() {} ~CommandOptions() override = default; @@ -4681,7 +4670,7 @@ public: return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options); } - uint32_t m_id; + uint32_t m_id = 0; }; bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -4717,7 +4706,6 @@ public: result.AppendErrorWithFormat( "'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4732,7 +4720,6 @@ public: if (!success) { result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4768,7 +4755,6 @@ public: result.AppendErrorWithFormat( "'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -4783,7 +4769,6 @@ public: if (!success) { result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); - result.SetStatus(eReturnStatusFailed); return false; } diff --git a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 5e3726548369..2785c3b08125 100644 --- a/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -44,9 +44,9 @@ typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP; typedef std::shared_ptr<RSScriptGroupDescriptor> RSScriptGroupDescriptorSP; struct RSCoordinate { - uint32_t x, y, z; + uint32_t x = 0, y = 0, z = 0; - RSCoordinate() : x(), y(), z(){}; + RSCoordinate() = default; bool operator==(const lldb_renderscript::RSCoordinate &rhs) { return x == rhs.x && y == rhs.y && z == rhs.z; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 211eb9ce0d3a..7ff917518b64 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -42,9 +42,7 @@ using namespace lldb_private; LLDB_PLUGIN_DEFINE(ObjectContainerBSDArchive) -ObjectContainerBSDArchive::Object::Object() - : ar_name(), modification_time(0), uid(0), gid(0), mode(0), size(0), - file_offset(0), file_size(0) {} +ObjectContainerBSDArchive::Object::Object() : ar_name() {} void ObjectContainerBSDArchive::Object::Clear() { ar_name.Clear(); @@ -142,7 +140,7 @@ ObjectContainerBSDArchive::Archive::Archive(const lldb_private::ArchSpec &arch, : m_arch(arch), m_modification_time(time), m_file_offset(file_offset), m_objects(), m_data(data) {} -ObjectContainerBSDArchive::Archive::~Archive() {} +ObjectContainerBSDArchive::Archive::~Archive() = default; size_t ObjectContainerBSDArchive::Archive::ParseObjects() { DataExtractor &data = m_data; @@ -375,7 +373,7 @@ void ObjectContainerBSDArchive::SetArchive(Archive::shared_ptr &archive_sp) { m_archive_sp = archive_sp; } -ObjectContainerBSDArchive::~ObjectContainerBSDArchive() {} +ObjectContainerBSDArchive::~ObjectContainerBSDArchive() = default; bool ObjectContainerBSDArchive::ParseHeader() { if (m_archive_sp.get() == nullptr) { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index f6862afff8a0..9830e9b5d1b2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -84,25 +84,25 @@ protected: lldb_private::ConstString ar_name; /// Object modification time in the archive. - uint32_t modification_time; + uint32_t modification_time = 0; /// Object user id in the archive. - uint16_t uid; + uint16_t uid = 0; /// Object group id in the archive. - uint16_t gid; + uint16_t gid = 0; /// Object octal file permissions in the archive. - uint16_t mode; + uint16_t mode = 0; /// Object size in bytes in the archive. - uint32_t size; + uint32_t size = 0; /// File offset in bytes from the beginning of the file of the object data. - lldb::offset_t file_offset; + lldb::offset_t file_offset = 0; /// Length of the object data. - lldb::offset_t file_size; + lldb::offset_t file_size = 0; }; class Archive { diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index cad9ce218b10..a5e86f0c2c1b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/LZMA.h" @@ -37,6 +38,7 @@ #include "llvm/Object/Decompressor.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/CRC.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/MipsABIFlags.h" @@ -857,8 +859,7 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) { if (symbol.d_tag == DT_MIPS_RLD_MAP) { // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer. Address addr; - if (target->ReadPointerFromMemory(dyn_base + offset, false, error, - addr)) + if (target->ReadPointerFromMemory(dyn_base + offset, error, addr, true)) return addr; } if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) { @@ -866,7 +867,7 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) { // relative to the address of the tag. uint64_t rel_offset; rel_offset = target->ReadUnsignedIntegerFromMemory( - dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error); + dyn_base + offset, GetAddressByteSize(), UINT64_MAX, error, true); if (error.Success() && rel_offset != UINT64_MAX) { Address addr; addr_t debug_ptr_address = @@ -1861,7 +1862,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { // unified section list. if (GetType() != eTypeDebugInfo) unified_section_list = *m_sections_up; - + // If there's a .gnu_debugdata section, we'll try to read the .symtab that's // embedded in there and replace the one in the original object file (if any). // If there's none in the orignal object file, we add it to it. @@ -1879,7 +1880,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { unified_section_list.AddSection(symtab_section_sp); } } - } + } } std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { @@ -1923,7 +1924,7 @@ std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture(); if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec)) return m_gnu_debug_data_object_file; - + return nullptr; } @@ -2707,6 +2708,9 @@ Symtab *ObjectFileELF::GetSymtab() { if (!module_sp) return nullptr; + Progress progress(llvm::formatv("Parsing symbol table for {0}", + m_file.GetFilename().AsCString("<Unknown>"))); + // We always want to use the main object file so we (hopefully) only have one // cached copy of our symtab, dynamic sections, etc. ObjectFile *module_obj_file = module_sp->GetObjectFile(); @@ -2770,14 +2774,14 @@ Symtab *ObjectFileELF::GetSymtab() { user_id_t reloc_id = reloc_section->GetID(); const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id); - assert(reloc_header); - - if (m_symtab_up == nullptr) - m_symtab_up = - std::make_unique<Symtab>(reloc_section->GetObjectFile()); + if (reloc_header) { + if (m_symtab_up == nullptr) + m_symtab_up = + std::make_unique<Symtab>(reloc_section->GetObjectFile()); - ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header, - reloc_id); + ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header, + reloc_id); + } } } @@ -2809,31 +2813,37 @@ Symtab *ObjectFileELF::GetSymtab() { if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress( entry_point_file_addr)) { uint64_t symbol_id = m_symtab_up->GetNumSymbols(); - Symbol symbol(symbol_id, - GetNextSyntheticSymbolName().GetCString(), // Symbol name. - eSymbolTypeCode, // Type of this symbol. - true, // Is this globally visible? - false, // Is this symbol debug info? - false, // Is this symbol a trampoline? - true, // Is this symbol artificial? - entry_point_addr.GetSection(), // Section where this - // symbol is defined. - 0, // Offset in section or symbol value. - 0, // Size. - false, // Size is valid. - false, // Contains linker annotations? - 0); // Symbol flags. - m_symtab_up->AddSymbol(symbol); + // Don't set the name for any synthetic symbols, the Symbol + // object will generate one if needed when the name is accessed + // via accessors. + SectionSP section_sp = entry_point_addr.GetSection(); + Symbol symbol( + /*symID=*/symbol_id, + /*name=*/llvm::StringRef(), // Name will be auto generated. + /*type=*/eSymbolTypeCode, + /*external=*/true, + /*is_debug=*/false, + /*is_trampoline=*/false, + /*is_artificial=*/true, + /*section_sp=*/section_sp, + /*offset=*/0, + /*size=*/0, // FDE can span multiple symbols so don't use its size. + /*size_is_valid=*/false, + /*contains_linker_annotations=*/false, + /*flags=*/0); // When the entry point is arm thumb we need to explicitly set its // class address to reflect that. This is important because expression // evaluation relies on correctly setting a breakpoint at this // address. if (arch.GetMachine() == llvm::Triple::arm && - (entry_point_file_addr & 1)) + (entry_point_file_addr & 1)) { + symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1); m_address_class_map[entry_point_file_addr ^ 1] = AddressClass::eCodeAlternateISA; - else + } else { m_address_class_map[entry_point_file_addr] = AddressClass::eCode; + } + m_symtab_up->AddSymbol(symbol); } } @@ -2897,8 +2907,11 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, // recalculate the index first. std::vector<Symbol> new_symbols; - eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols]( - lldb::addr_t file_addr, uint32_t size, dw_offset_t) { + size_t num_symbols = symbol_table->GetNumSymbols(); + uint64_t last_symbol_id = + num_symbols ? symbol_table->SymbolAtIndex(num_symbols - 1)->GetID() : 0; + eh_frame->ForEachFDEEntries([&](lldb::addr_t file_addr, uint32_t size, + dw_offset_t) { Symbol *symbol = symbol_table->FindSymbolAtFileAddress(file_addr); if (symbol) { if (!symbol->GetByteSizeIsValid()) { @@ -2910,22 +2923,24 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, section_list->FindSectionContainingFileAddress(file_addr); if (section_sp) { addr_t offset = file_addr - section_sp->GetFileAddress(); - const char *symbol_name = GetNextSyntheticSymbolName().GetCString(); - uint64_t symbol_id = symbol_table->GetNumSymbols(); + uint64_t symbol_id = ++last_symbol_id; + // Don't set the name for any synthetic symbols, the Symbol + // object will generate one if needed when the name is accessed + // via accessors. Symbol eh_symbol( - symbol_id, // Symbol table index. - symbol_name, // Symbol name. - eSymbolTypeCode, // Type of this symbol. - true, // Is this globally visible? - false, // Is this symbol debug info? - false, // Is this symbol a trampoline? - true, // Is this symbol artificial? - section_sp, // Section in which this symbol is defined or null. - offset, // Offset in section or symbol value. - 0, // Size: Don't specify the size as an FDE can - false, // Size is valid: cover multiple symbols. - false, // Contains linker annotations? - 0); // Symbol flags. + /*symID=*/symbol_id, + /*name=*/llvm::StringRef(), // Name will be auto generated. + /*type=*/eSymbolTypeCode, + /*external=*/true, + /*is_debug=*/false, + /*is_trampoline=*/false, + /*is_artificial=*/true, + /*section_sp=*/section_sp, + /*offset=*/offset, + /*size=*/0, // FDE can span multiple symbols so don't use its size. + /*size_is_valid=*/false, + /*contains_linker_annotations=*/false, + /*flags=*/0); new_symbols.push_back(eh_symbol); } } diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 062271f1caf0..e678c2f5f011 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -9,7 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H #define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H -#include <stdint.h> +#include <cstdint> #include <vector> @@ -22,13 +22,13 @@ #include "ELFHeader.h" struct ELFNote { - elf::elf_word n_namesz; - elf::elf_word n_descsz; - elf::elf_word n_type; + elf::elf_word n_namesz = 0; + elf::elf_word n_descsz = 0; + elf::elf_word n_type = 0; std::string n_name; - ELFNote() : n_namesz(0), n_descsz(0), n_type(0) {} + ELFNote() = default; /// Parse an ELFNote entry from the given DataExtractor starting at position /// \p offset. diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index 93c2c9f945fe..f93ac9261afd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -100,7 +100,7 @@ ObjectFileJIT::ObjectFileJIT(const lldb::ModuleSP &module_sp, } } -ObjectFileJIT::~ObjectFileJIT() {} +ObjectFileJIT::~ObjectFileJIT() = default; bool ObjectFileJIT::ParseHeader() { // JIT code is never in a file, nor is it required to have any header diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp index 35a823e9a28f..cb7bbeeca054 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -173,7 +173,7 @@ ObjectFilePDB::loadPDBFile(std::string PdbPath, if (ec || magic != llvm::file_magic::pdb) return nullptr; llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer = - llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, + llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false, /*RequiresNullTerminator=*/false); if (!ErrorOrBuffer) return nullptr; diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp index 6c29c2326212..5272da9ab33a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -196,7 +196,7 @@ bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) { m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), section_length, section_id, *sect_name}); *offset_ptr += (c.tell() + section_length); - } else if (section_id <= llvm::wasm::WASM_SEC_EVENT) { + } else if (section_id <= llvm::wasm::WASM_SEC_TAG) { m_sect_infos.push_back(section_info{*offset_ptr + c.tell(), static_cast<uint32_t>(payload_len), section_id, ConstString()}); diff --git a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 4350010f0296..730c88f96e13 100644 --- a/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -91,13 +91,13 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process, std::string os_plugin_class_name( python_module_path.GetFilename().AsCString("")); if (!os_plugin_class_name.empty()) { - const bool init_session = false; + LoadScriptOptions options; char python_module_path_cstr[PATH_MAX]; python_module_path.GetPath(python_module_path_cstr, sizeof(python_module_path_cstr)); Status error; - if (m_interpreter->LoadScriptingModule(python_module_path_cstr, - init_session, error)) { + if (m_interpreter->LoadScriptingModule(python_module_path_cstr, options, + error)) { // Strip the ".py" extension if there is one size_t py_extension_pos = os_plugin_class_name.rfind(".py"); if (py_extension_pos != std::string::npos) @@ -115,7 +115,7 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process, } } -OperatingSystemPython::~OperatingSystemPython() {} +OperatingSystemPython::~OperatingSystemPython() = default; DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() { if (m_register_info_up == nullptr) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 6b39a83fd668..7b3d8a375bf6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -9,7 +9,7 @@ #include "PlatformFreeBSD.h" #include "lldb/Host/Config.h" -#include <stdio.h> +#include <cstdio> #if LLDB_ENABLE_POSIX #include <sys/utsname.h> #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index a5d73c942830..e3682b44e141 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -9,7 +9,7 @@ #include "PlatformNetBSD.h" #include "lldb/Host/Config.h" -#include <stdio.h> +#include <cstdio> #if LLDB_ENABLE_POSIX #include <sys/utsname.h> #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp index 2cd024f56ec9..012b688231a0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp @@ -9,7 +9,7 @@ #include "PlatformOpenBSD.h" #include "lldb/Host/Config.h" -#include <stdio.h> +#include <cstdio> #if LLDB_ENABLE_POSIX #include <sys/utsname.h> #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index 3628b0a2ce5e..7353132cd96f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -46,7 +46,7 @@ PlatformPOSIX::PlatformPOSIX(bool is_host) /// /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. -PlatformPOSIX::~PlatformPOSIX() {} +PlatformPOSIX::~PlatformPOSIX() = default; lldb_private::OptionGroupOptions *PlatformPOSIX::GetConnectionOptions( lldb_private::CommandInterpreter &interpreter) { @@ -578,7 +578,19 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, // __lldb_dlopen_result for consistency. The wrapper returns a void * but // doesn't use it because UtilityFunctions don't work with void returns at // present. + // + // Use lazy binding so as to not make dlopen()'s success conditional on + // forcing every symbol in the library. + // + // In general, the debugger should allow programs to load & run with + // libraries as far as they can, instead of defaulting to being super-picky + // about unavailable symbols. + // + // The value "1" appears to imply lazy binding (RTLD_LAZY) on both Darwin + // and other POSIX OSes. static const char *dlopen_wrapper_code = R"( + const int RTLD_LAZY = 1; + struct __lldb_dlopen_result { void *image_ptr; const char *error_str; @@ -595,7 +607,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, { // This is the case where the name is the full path: if (!path_strings) { - result_ptr->image_ptr = dlopen(name, 2); + result_ptr->image_ptr = dlopen(name, RTLD_LAZY); if (result_ptr->image_ptr) result_ptr->error_str = nullptr; return nullptr; @@ -609,7 +621,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, buffer[path_len] = '/'; char *target_ptr = buffer+path_len+1; memcpy((void *) target_ptr, (void *) name, name_len + 1); - result_ptr->image_ptr = dlopen(buffer, 2); + result_ptr->image_ptr = dlopen(buffer, RTLD_LAZY); if (result_ptr->image_ptr) { result_ptr->error_str = nullptr; break; @@ -659,7 +671,7 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx, // We are passing four arguments, the basename, the list of places to look, // a buffer big enough for all the path + name combos, and // a pointer to the storage we've made for the result: - value.SetValueType(Value::eValueTypeScalar); + value.SetValueType(Value::ValueType::Scalar); value.SetCompilerType(clang_void_pointer_type); arguments.PushValue(value); value.SetCompilerType(clang_char_pointer_type); @@ -994,13 +1006,6 @@ PlatformPOSIX::GetLibdlFunctionDeclarations(lldb_private::Process *process) { )"; } -size_t PlatformPOSIX::ConnectToWaitingProcesses(Debugger &debugger, - Status &error) { - if (m_remote_platform_sp) - return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); - return Platform::ConnectToWaitingProcesses(debugger, error); -} - ConstString PlatformPOSIX::GetFullNameForDylib(ConstString basename) { if (basename.IsEmpty()) return basename; diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 72c54f4147c2..1cba4c5eb2e9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -71,9 +71,6 @@ public: lldb_private::Status UnloadImage(lldb_private::Process *process, uint32_t image_token) override; - size_t ConnectToWaitingProcesses(lldb_private::Debugger &debugger, - lldb_private::Status &error) override; - lldb_private::ConstString GetFullNameForDylib(lldb_private::ConstString basename) override; protected: diff --git a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 6a4275d249f6..528208665a4e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -30,6 +30,7 @@ #include "lldb/Utility/UriParser.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" +#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" using namespace lldb; using namespace lldb_private; @@ -202,13 +203,16 @@ Status PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file, /// Default Constructor PlatformRemoteGDBServer::PlatformRemoteGDBServer() : Platform(false), // This is a remote platform - m_gdb_client() {} + m_gdb_client() { + m_gdb_client.SetPacketTimeout( + process_gdb_remote::ProcessGDBRemote::GetPacketTimeout()); +} /// Destructor. /// /// The destructor is virtual since this class is designed to be /// inherited from by the plug-in instance. -PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {} +PlatformRemoteGDBServer::~PlatformRemoteGDBServer() = default; bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { @@ -736,8 +740,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() { m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture()); StringExtractorGDBRemote response; - auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", - response, false); + auto result = + m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo", response); if (result != decltype(result)::Success || response.GetResponseType() != response.eResponse) @@ -839,7 +843,7 @@ size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger, GetPendingGdbServerList(connection_urls); for (size_t i = 0; i < connection_urls.size(); ++i) { - ConnectProcess(connection_urls[i].c_str(), "", debugger, nullptr, error); + ConnectProcess(connection_urls[i].c_str(), "gdb-remote", debugger, nullptr, error); if (error.Fail()) return i; // We already connected to i process succsessfully } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp index 5961ff4439db..d6426b3d2367 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp @@ -128,13 +128,20 @@ NativeProcessFreeBSD::Factory::Attach( return std::move(process_up); } +NativeProcessFreeBSD::Extension +NativeProcessFreeBSD::Factory::GetSupportedExtensions() const { + return Extension::multiprocess | Extension::fork | Extension::vfork | + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; +} + // Public Instance Methods NativeProcessFreeBSD::NativeProcessFreeBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop) - : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) { + : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch), + m_main_loop(mainloop) { if (m_terminal_fd != -1) { Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); assert(status.Success()); @@ -258,6 +265,26 @@ void NativeProcessFreeBSD::MonitorSIGTRAP(lldb::pid_t pid) { info.pl_lwpid); } + if (info.pl_flags & PL_FLAG_FORKED) { + assert(thread); + MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread); + return; + } + + if (info.pl_flags & PL_FLAG_VFORK_DONE) { + assert(thread); + if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) { + thread->SetStoppedByVForkDone(); + SetState(StateType::eStateStopped, true); + } else { + Status error = + PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0); + if (error.Fail()) + SetState(StateType::eStateInvalid); + } + return; + } + if (info.pl_flags & PL_FLAG_SI) { assert(info.pl_siginfo.si_signo == SIGTRAP); LLDB_LOG(log, "SIGTRAP siginfo: si_code = {0}, pid = {1}", @@ -705,17 +732,17 @@ NativeProcessFreeBSD::GetFileLoadAddress(const llvm::StringRef &file_name, void NativeProcessFreeBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - // Process all pending waitpid notifications. int status; ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG); if (wait_pid == 0) - return; // We are done. + return; if (wait_pid == -1) { Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); + return; } WaitStatus wait_status = WaitStatus::Decode(status); @@ -885,7 +912,7 @@ Status NativeProcessFreeBSD::SetupTrace() { PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events)); if (status.Fail()) return status; - events |= PTRACE_LWP; + events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK; status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events)); if (status.Fail()) return status; @@ -919,3 +946,66 @@ Status NativeProcessFreeBSD::ReinitializeThreads() { bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const { return !m_arch.IsMIPS(); } + +void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid, bool is_vfork, + NativeThreadFreeBSD &parent_thread) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "fork, child_pid={0}", child_pid); + + int status; + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0); + if (wait_pid != child_pid) { + LLDB_LOG(log, + "waiting for pid {0} failed. Assuming the pid has " + "disappeared in the meantime", + child_pid); + return; + } + if (WIFEXITED(status)) { + LLDB_LOG(log, + "waiting for pid {0} returned an 'exited' event. Not " + "tracking it.", + child_pid); + return; + } + + struct ptrace_lwpinfo info; + const auto siginfo_err = PtraceWrapper(PT_LWPINFO, child_pid, &info, sizeof(info)); + if (siginfo_err.Fail()) { + LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err); + return; + } + assert(info.pl_event == PL_EVENT_SIGNAL); + lldb::tid_t child_tid = info.pl_lwpid; + + std::unique_ptr<NativeProcessFreeBSD> child_process{ + new NativeProcessFreeBSD(static_cast<::pid_t>(child_pid), m_terminal_fd, + m_delegate, m_arch, m_main_loop)}; + if (!is_vfork) + child_process->m_software_breakpoints = m_software_breakpoints; + + Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork; + if ((m_enabled_extensions & expected_ext) == expected_ext) { + child_process->SetupTrace(); + for (const auto &thread : child_process->m_threads) + static_cast<NativeThreadFreeBSD &>(*thread).SetStoppedBySignal(SIGSTOP); + child_process->SetState(StateType::eStateStopped, false); + + m_delegate.NewSubprocess(this, std::move(child_process)); + if (is_vfork) + parent_thread.SetStoppedByVFork(child_pid, child_tid); + else + parent_thread.SetStoppedByFork(child_pid, child_tid); + SetState(StateType::eStateStopped, true); + } else { + child_process->Detach(); + Status pt_error = + PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0); + if (pt_error.Fail()) { + LLDB_LOG_ERROR(log, pt_error.ToError(), + "unable to resume parent process {1}: {0}", GetID()); + SetState(StateType::eStateInvalid); + } + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h index ceffc370ca33..7ec9d17d4cf4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h @@ -39,6 +39,8 @@ public: llvm::Expected<std::unique_ptr<NativeProcessProtocol>> Attach(lldb::pid_t pid, NativeDelegate &native_delegate, MainLoop &mainloop) const override; + + Extension GetSupportedExtensions() const override; }; // NativeProcessProtocol Interface @@ -96,6 +98,7 @@ protected: private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; + MainLoop& m_main_loop; LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; @@ -113,6 +116,8 @@ private: void MonitorSIGSTOP(lldb::pid_t pid); void MonitorSIGTRAP(lldb::pid_t pid); void MonitorSignal(lldb::pid_t pid, int signal); + void MonitorClone(::pid_t child_pid, bool is_vfork, + NativeThreadFreeBSD &parent_thread); Status PopulateMemoryRegionCache(); void SigchldHandler(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp index e98e0a8a0caa..4578138a89b3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp @@ -37,14 +37,12 @@ NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextRegisterInfo( - native_thread, new RegisterInfoPOSIX_arm64(target_arch)) + native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0)) #ifdef LLDB_HAS_FREEBSD_WATCHPOINT , m_read_dbreg(false) #endif { - GetRegisterInfo().ConfigureVectorRegisterInfos( - RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs)); } @@ -79,8 +77,6 @@ Status NativeRegisterContextFreeBSD_arm64::ReadRegisterSet(uint32_t set) { return NativeProcessFreeBSD::PtraceWrapper( PT_GETFPREGS, m_thread.GetID(), m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); - case RegisterInfoPOSIX_arm64::SVERegSet: - return Status("not supported"); } llvm_unreachable("NativeRegisterContextFreeBSD_arm64::ReadRegisterSet"); } @@ -94,8 +90,6 @@ Status NativeRegisterContextFreeBSD_arm64::WriteRegisterSet(uint32_t set) { return NativeProcessFreeBSD::PtraceWrapper( PT_SETFPREGS, m_thread.GetID(), m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); - case RegisterInfoPOSIX_arm64::SVERegSet: - return Status("not supported"); } llvm_unreachable("NativeRegisterContextFreeBSD_arm64::WriteRegisterSet"); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp index d5052e7d1b3a..9328d606ad26 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp @@ -260,7 +260,7 @@ NativeRegisterContextFreeBSD_x86_64::NativeRegisterContextFreeBSD_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextRegisterInfo( native_thread, CreateRegisterInfoInterface(target_arch)), - m_regset_offsets({0}) { + NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) { assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize()); std::array<uint32_t, MaxRegSet + 1> first_regnos; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp index 63be12fc7b2b..80b3527aebce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.cpp @@ -130,6 +130,30 @@ void NativeThreadFreeBSD::SetStoppedByWatchpoint(uint32_t wp_index) { m_stop_info.details.signal.signo = SIGTRAP; } +void NativeThreadFreeBSD::SetStoppedByFork(lldb::pid_t child_pid, + lldb::tid_t child_tid) { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonFork; + m_stop_info.details.fork.child_pid = child_pid; + m_stop_info.details.fork.child_tid = child_tid; +} + +void NativeThreadFreeBSD::SetStoppedByVFork(lldb::pid_t child_pid, + lldb::tid_t child_tid) { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonVFork; + m_stop_info.details.fork.child_pid = child_pid; + m_stop_info.details.fork.child_tid = child_tid; +} + +void NativeThreadFreeBSD::SetStoppedByVForkDone() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonVForkDone; +} + void NativeThreadFreeBSD::SetStoppedWithNoReason() { SetStopped(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h index 249d2486b4f7..3ec6daa409e4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeThreadFreeBSD.h @@ -59,6 +59,9 @@ private: void SetStoppedByTrace(); void SetStoppedByExec(); void SetStoppedByWatchpoint(uint32_t wp_index); + void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid); + void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid); + void SetStoppedByVForkDone(); void SetStoppedWithNoReason(); void SetStopped(); void SetRunning(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp index 57f0eb3cceb6..9ea1a16b8785 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -133,13 +133,20 @@ NativeProcessNetBSD::Factory::Attach( return std::move(process_up); } +NativeProcessNetBSD::Extension +NativeProcessNetBSD::Factory::GetSupportedExtensions() const { + return Extension::multiprocess | Extension::fork | Extension::vfork | + Extension::pass_signals | Extension::auxv | Extension::libraries_svr4; +} + // Public Instance Methods NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop) - : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) { + : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch), + m_main_loop(mainloop) { if (m_terminal_fd != -1) { Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK); assert(status.Success()); @@ -256,6 +263,33 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) { SetState(StateType::eStateStopped, true); return; } + case TRAP_CHLD: { + ptrace_state_t pst; + Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst)); + if (error.Fail()) { + SetState(StateType::eStateInvalid); + return; + } + + assert(thread); + if (pst.pe_report_event == PTRACE_VFORK_DONE) { + if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) { + thread->SetStoppedByVForkDone(); + SetState(StateType::eStateStopped, true); + } else { + Status error = + PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0); + if (error.Fail()) + SetState(StateType::eStateInvalid); + } + } else { + assert(pst.pe_report_event == PTRACE_FORK || + pst.pe_report_event == PTRACE_VFORK); + MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK, + *thread); + } + return; + } case TRAP_LWP: { ptrace_state_t pst; Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst)); @@ -510,7 +544,7 @@ Status NativeProcessNetBSD::Detach() { if (GetID() == LLDB_INVALID_PROCESS_ID) return error; - return PtraceWrapper(PT_DETACH, GetID()); + return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1)); } Status NativeProcessNetBSD::Signal(int signo) { @@ -738,17 +772,17 @@ Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name, void NativeProcessNetBSD::SigchldHandler() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); - // Process all pending waitpid notifications. int status; ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG); if (wait_pid == 0) - return; // We are done. + return; if (wait_pid == -1) { Status error(errno, eErrorTypePOSIX); LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error); + return; } WaitStatus wait_status = WaitStatus::Decode(status); @@ -936,8 +970,9 @@ Status NativeProcessNetBSD::SetupTrace() { PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events)); if (status.Fail()) return status; - // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN? - events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; + // TODO: PTRACE_POSIX_SPAWN? + events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK | + PTRACE_VFORK | PTRACE_VFORK_DONE; status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events)); if (status.Fail()) return status; @@ -974,3 +1009,67 @@ Status NativeProcessNetBSD::ReinitializeThreads() { return error; } + +void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork, + NativeThreadNetBSD &parent_thread) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "clone, child_pid={0}", child_pid); + + int status; + ::pid_t wait_pid = + llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0); + if (wait_pid != child_pid) { + LLDB_LOG(log, + "waiting for pid {0} failed. Assuming the pid has " + "disappeared in the meantime", + child_pid); + return; + } + if (WIFEXITED(status)) { + LLDB_LOG(log, + "waiting for pid {0} returned an 'exited' event. Not " + "tracking it.", + child_pid); + return; + } + + ptrace_siginfo_t info; + const auto siginfo_err = + PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info)); + if (siginfo_err.Fail()) { + LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err); + return; + } + assert(info.psi_lwpid >= 0); + lldb::tid_t child_tid = info.psi_lwpid; + + std::unique_ptr<NativeProcessNetBSD> child_process{ + new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd, + m_delegate, m_arch, m_main_loop)}; + if (!is_vfork) + child_process->m_software_breakpoints = m_software_breakpoints; + + Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork; + if ((m_enabled_extensions & expected_ext) == expected_ext) { + child_process->SetupTrace(); + for (const auto &thread : child_process->m_threads) + static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP); + child_process->SetState(StateType::eStateStopped, false); + + m_delegate.NewSubprocess(this, std::move(child_process)); + if (is_vfork) + parent_thread.SetStoppedByVFork(child_pid, child_tid); + else + parent_thread.SetStoppedByFork(child_pid, child_tid); + SetState(StateType::eStateStopped, true); + } else { + child_process->Detach(); + Status pt_error = + PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0); + if (pt_error.Fail()) { + LLDB_LOG_ERROR(log, std::move(pt_error.ToError()), + "unable to resume parent process {1}: {0}", GetID()); + SetState(StateType::eStateInvalid); + } + } +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h index 3d59a4f72e94..90d32aa6069d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h @@ -36,6 +36,8 @@ public: llvm::Expected<std::unique_ptr<NativeProcessProtocol>> Attach(lldb::pid_t pid, NativeDelegate &native_delegate, MainLoop &mainloop) const override; + + Extension GetSupportedExtensions() const override; }; // NativeProcessProtocol Interface @@ -89,6 +91,7 @@ public: private: MainLoop::SignalHandleUP m_sigchld_handle; ArchSpec m_arch; + MainLoop& m_main_loop; LazyBool m_supports_mem_region = eLazyBoolCalculate; std::vector<std::pair<MemoryRegionInfo, FileSpec>> m_mem_region_cache; @@ -106,6 +109,8 @@ private: void MonitorSIGSTOP(lldb::pid_t pid); void MonitorSIGTRAP(lldb::pid_t pid); void MonitorSignal(lldb::pid_t pid, int signal); + void MonitorClone(::pid_t child_pid, bool is_vfork, + NativeThreadNetBSD &parent_thread); Status PopulateMemoryRegionCache(); void SigchldHandler(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp index ed1884c94a4b..3d164eadbea7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp @@ -29,8 +29,8 @@ #include <x86/specialreg.h> #include <elf.h> #include <err.h> -#include <stdint.h> -#include <stdlib.h> +#include <cstdint> +#include <cstdlib> // clang-format on using namespace lldb_private; @@ -267,7 +267,7 @@ NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64( const ArchSpec &target_arch, NativeThreadProtocol &native_thread) : NativeRegisterContextRegisterInfo( native_thread, CreateRegisterInfoInterface(target_arch)), - m_regset_offsets({0}) { + NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) { assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize()); std::array<uint32_t, MaxRegularRegSet + 1> first_regnos; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp index 1a3fd4d646ae..400b89a5fddf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp @@ -130,6 +130,30 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) { m_stop_info.details.signal.signo = SIGTRAP; } +void NativeThreadNetBSD::SetStoppedByFork(lldb::pid_t child_pid, + lldb::tid_t child_tid) { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonFork; + m_stop_info.details.fork.child_pid = child_pid; + m_stop_info.details.fork.child_tid = child_tid; +} + +void NativeThreadNetBSD::SetStoppedByVFork(lldb::pid_t child_pid, + lldb::tid_t child_tid) { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonVFork; + m_stop_info.details.fork.child_pid = child_pid; + m_stop_info.details.fork.child_tid = child_tid; +} + +void NativeThreadNetBSD::SetStoppedByVForkDone() { + SetStopped(); + + m_stop_info.reason = StopReason::eStopReasonVForkDone; +} + void NativeThreadNetBSD::SetStoppedWithNoReason() { SetStopped(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h index d4e21bd2bdaa..ee9305337fda 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h @@ -59,6 +59,9 @@ private: void SetStoppedByTrace(); void SetStoppedByExec(); void SetStoppedByWatchpoint(uint32_t wp_index); + void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid); + void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid); + void SetStoppedByVForkDone(); void SetStoppedWithNoReason(); void SetStopped(); void SetRunning(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h index f5213891d976..24acdc08e900 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.h @@ -11,7 +11,7 @@ #include "lldb/lldb-types.h" -#include <signal.h> +#include <csignal> #include <string> diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h index dcfa9290ff50..c01409940daa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/POSIX/NativeProcessELF.h @@ -21,6 +21,9 @@ namespace lldb_private { class NativeProcessELF : public NativeProcessProtocol { using NativeProcessProtocol::NativeProcessProtocol; +public: + llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type); + protected: template <typename T> struct ELFLinkMap { T l_addr; @@ -30,8 +33,6 @@ protected: T l_prev; }; - llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type); - lldb::addr_t GetSharedLibraryInfoAddress() override; template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN> diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 5463a071503c..a85d7bd6f525 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -697,6 +697,14 @@ RegisterInfo *DynamicRegisterInfo::GetRegisterInfoAtIndex(uint32_t i) { return nullptr; } +const RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(uint32_t kind, + uint32_t num) const { + uint32_t reg_index = ConvertRegisterKindToRegisterNumber(kind, num); + if (reg_index != LLDB_INVALID_REGNUM) + return &m_regs[reg_index]; + return nullptr; +} + const RegisterSet *DynamicRegisterInfo::GetRegisterSet(uint32_t i) const { if (i < m_sets.size()) return &m_sets[i]; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h index fbf9db685b71..7e90454c6d9d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -60,6 +60,9 @@ public: uint32_t ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num) const; + const lldb_private::RegisterInfo *GetRegisterInfo(uint32_t kind, + uint32_t num) const; + void Dump() const; void Clear(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp index 9b9522955de9..7749dc6f5d51 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -30,7 +30,7 @@ HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, // Destructor -HistoryUnwind::~HistoryUnwind() {} +HistoryUnwind::~HistoryUnwind() = default; void HistoryUnwind::DoClear() { std::lock_guard<std::recursive_mutex> guard(m_unwind_mutex); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h index 7f6f7cf5832d..817dca336de7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h @@ -9,7 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H -#include <stdint.h> +#include <cstdint> namespace lldb_private { namespace sve { @@ -65,7 +65,7 @@ const uint16_t sve_context_size = 16; * The same convention applies when returning from a signal: a caller * will need to remove or resize the sve_context block if it wants to * make the SVE registers live when they were previously non-live or - * vice-versa. This may require the the caller to allocate fresh + * vice-versa. This may require the caller to allocate fresh * memory and/or move other context blocks in the signal frame. * * Changing the vector length during signal return is not permitted: diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp new file mode 100644 index 000000000000..d74b66b58afc --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp @@ -0,0 +1,200 @@ +//===-- MemoryTagManagerAArch64MTE.cpp --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MemoryTagManagerAArch64MTE.h" + +using namespace lldb_private; + +static const unsigned MTE_START_BIT = 56; +static const unsigned MTE_TAG_MAX = 0xf; +static const unsigned MTE_GRANULE_SIZE = 16; + +lldb::addr_t +MemoryTagManagerAArch64MTE::GetLogicalTag(lldb::addr_t addr) const { + return (addr >> MTE_START_BIT) & MTE_TAG_MAX; +} + +lldb::addr_t +MemoryTagManagerAArch64MTE::RemoveNonAddressBits(lldb::addr_t addr) const { + // Here we're ignoring the whole top byte. If you've got MTE + // you must also have TBI (top byte ignore). + // The other 4 bits could contain other extension bits or + // user metadata. + return addr & ~((lldb::addr_t)0xFF << MTE_START_BIT); +} + +ptrdiff_t MemoryTagManagerAArch64MTE::AddressDiff(lldb::addr_t addr1, + lldb::addr_t addr2) const { + return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2); +} + +lldb::addr_t MemoryTagManagerAArch64MTE::GetGranuleSize() const { + return MTE_GRANULE_SIZE; +} + +int32_t MemoryTagManagerAArch64MTE::GetAllocationTagType() const { + return eMTE_allocation; +} + +size_t MemoryTagManagerAArch64MTE::GetTagSizeInBytes() const { return 1; } + +MemoryTagManagerAArch64MTE::TagRange +MemoryTagManagerAArch64MTE::ExpandToGranule(TagRange range) const { + // Ignore reading a length of 0 + if (!range.IsValid()) + return range; + + const size_t granule = GetGranuleSize(); + + // Align start down to granule start + lldb::addr_t new_start = range.GetRangeBase(); + lldb::addr_t align_down_amount = new_start % granule; + new_start -= align_down_amount; + + // Account for the distance we moved the start above + size_t new_len = range.GetByteSize() + align_down_amount; + // Then align up to the end of the granule + size_t align_up_amount = granule - (new_len % granule); + if (align_up_amount != granule) + new_len += align_up_amount; + + return TagRange(new_start, new_len); +} + +llvm::Expected<MemoryTagManager::TagRange> +MemoryTagManagerAArch64MTE::MakeTaggedRange( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const { + // First check that the range is not inverted. + // We must remove tags here otherwise an address with a higher + // tag value will always be > the other. + ptrdiff_t len = AddressDiff(end_addr, addr); + if (len <= 0) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "End address (0x%" PRIx64 + ") must be greater than the start address (0x%" PRIx64 ")", + end_addr, addr); + } + + // Region addresses will not have memory tags. So when searching + // we must use an untagged address. + MemoryRegionInfo::RangeType tag_range(RemoveNonAddressBits(addr), len); + tag_range = ExpandToGranule(tag_range); + + // Make a copy so we can use the original for errors and the final return. + MemoryRegionInfo::RangeType remaining_range(tag_range); + + // While there are parts of the range that don't have a matching tagged memory + // region + while (remaining_range.IsValid()) { + // Search for a region that contains the start of the range + MemoryRegionInfos::const_iterator region = std::find_if( + memory_regions.cbegin(), memory_regions.cend(), + [&remaining_range](const MemoryRegionInfo ®ion) { + return region.GetRange().Contains(remaining_range.GetRangeBase()); + }); + + if (region == memory_regions.cend() || + region->GetMemoryTagged() != MemoryRegionInfo::eYes) { + // Some part of this range is untagged (or unmapped) so error + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Address range 0x%" PRIx64 ":0x%" PRIx64 + " is not in a memory tagged region", + tag_range.GetRangeBase(), + tag_range.GetRangeEnd()); + } + + // We've found some part of the range so remove that part and continue + // searching for the rest. Moving the base "slides" the range so we need to + // save/restore the original end. If old_end is less than the new base, the + // range will be set to have 0 size and we'll exit the while. + lldb::addr_t old_end = remaining_range.GetRangeEnd(); + remaining_range.SetRangeBase(region->GetRange().GetRangeEnd()); + remaining_range.SetRangeEnd(old_end); + } + + // Every part of the range is contained within a tagged memory region. + return tag_range; +} + +llvm::Expected<std::vector<lldb::addr_t>> +MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags, + size_t granules /*=0*/) const { + // 0 means don't check the number of tags before unpacking + if (granules) { + size_t num_tags = tags.size() / GetTagSizeInBytes(); + if (num_tags != granules) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Packed tag data size does not match expected number of tags. " + "Expected %zu tag(s) for %zu granule(s), got %zu tag(s).", + granules, granules, num_tags); + } + } + + // (if bytes per tag was not 1, we would reconstruct them here) + + std::vector<lldb::addr_t> unpacked; + unpacked.reserve(tags.size()); + for (auto it = tags.begin(); it != tags.end(); ++it) { + // Check all tags are in range + if (*it > MTE_TAG_MAX) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Found tag 0x%x which is > max MTE tag value of 0x%x.", *it, + MTE_TAG_MAX); + } + unpacked.push_back(*it); + } + + return unpacked; +} + +llvm::Expected<std::vector<uint8_t>> MemoryTagManagerAArch64MTE::PackTags( + const std::vector<lldb::addr_t> &tags) const { + std::vector<uint8_t> packed; + packed.reserve(tags.size() * GetTagSizeInBytes()); + + for (auto tag : tags) { + if (tag > MTE_TAG_MAX) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Found tag 0x%" PRIx64 + " which is > max MTE tag value of 0x%x.", + tag, MTE_TAG_MAX); + } + packed.push_back(static_cast<uint8_t>(tag)); + } + + return packed; +} + +llvm::Expected<std::vector<lldb::addr_t>> +MemoryTagManagerAArch64MTE::RepeatTagsForRange( + const std::vector<lldb::addr_t> &tags, TagRange range) const { + std::vector<lldb::addr_t> new_tags; + + // If the range is not empty + if (range.IsValid()) { + if (tags.empty()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Expected some tags to cover given range, got zero."); + } + + // We assume that this range has already been expanded/aligned to granules + size_t granules = range.GetByteSize() / GetGranuleSize(); + new_tags.reserve(granules); + for (size_t to_copy = 0; granules > 0; granules -= to_copy) { + to_copy = granules > tags.size() ? tags.size() : granules; + new_tags.insert(new_tags.end(), tags.begin(), tags.begin() + to_copy); + } + } + + return new_tags; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h new file mode 100644 index 000000000000..d4e8249da93f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h @@ -0,0 +1,53 @@ +//===-- MemoryTagManagerAArch64MTE.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H + +#include "lldb/Target/MemoryTagManager.h" + +namespace lldb_private { + +class MemoryTagManagerAArch64MTE : public MemoryTagManager { +public: + // This enum is supposed to be shared for all of AArch64 but until + // there are more tag types than MTE, it will live here. + enum MTETagTypes { + eMTE_logical = 0, + eMTE_allocation = 1, + }; + + lldb::addr_t GetGranuleSize() const override; + int32_t GetAllocationTagType() const override; + size_t GetTagSizeInBytes() const override; + + lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override; + lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override; + ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override; + + TagRange ExpandToGranule(TagRange range) const override; + + llvm::Expected<TagRange> MakeTaggedRange( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const override; + + llvm::Expected<std::vector<lldb::addr_t>> + UnpackTagsData(const std::vector<uint8_t> &tags, + size_t granules = 0) const override; + + llvm::Expected<std::vector<uint8_t>> + PackTags(const std::vector<lldb::addr_t> &tags) const override; + + llvm::Expected<std::vector<lldb::addr_t>> + RepeatTagsForRange(const std::vector<lldb::addr_t> &tags, + TagRange range) const override; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_MEMORYTAGMANAGERAARCH64MTE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp index 5c05baf71764..feee857cfe5f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp @@ -421,6 +421,9 @@ Status NativeRegisterContextDBReg_arm64::GetWatchpointHitIndex( if (error) return Status(std::move(error)); + // Mask off ignored bits from watchpoint trap address. + trap_addr = FixWatchpointHitAddress(trap_addr); + uint32_t watch_size; lldb::addr_t watch_addr; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h index 12ef5571f64c..3da0b0407ce6 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.h @@ -72,6 +72,9 @@ protected: virtual llvm::Error ReadHardwareDebugInfo() = 0; virtual llvm::Error WriteHardwareDebugRegs(DREGType hwbType) = 0; + virtual lldb::addr_t FixWatchpointHitAddress(lldb::addr_t hit_addr) { + return hit_addr; + } }; } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h index c0c6ce29eab5..a4ed8bfb97ea 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_x86.h @@ -16,6 +16,12 @@ namespace lldb_private { class NativeRegisterContextDBReg_x86 : public virtual NativeRegisterContextRegisterInfo { public: + // NB: This constructor is here only because gcc<=6.5 requires a virtual base + // class initializer on abstract class (even though it is never used). It can + // be deleted once we move to gcc>=7.0. + NativeRegisterContextDBReg_x86(NativeThreadProtocol &thread) + : NativeRegisterContextRegisterInfo(thread, nullptr) {} + Status IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; Status GetWatchpointHitIndex(uint32_t &wp_index, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index eef4541e7edd..7e38091738e3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -922,7 +922,7 @@ RegisterContextDarwin_arm::RegisterContextDarwin_arm( } } -RegisterContextDarwin_arm::~RegisterContextDarwin_arm() {} +RegisterContextDarwin_arm::~RegisterContextDarwin_arm() = default; void RegisterContextDarwin_arm::InvalidateAllRegisters() { InvalidateAllRegisterStates(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index 9fc275276699..b98b2f35c23e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -104,7 +104,7 @@ RegisterContextDarwin_arm64::RegisterContextDarwin_arm64( } } -RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() {} +RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() = default; void RegisterContextDarwin_arm64::InvalidateAllRegisters() { InvalidateAllRegisterStates(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index c5ebddc56b6c..95f8132a990c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -15,7 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" -#include <stddef.h> +#include <cstddef> #include <memory> @@ -405,7 +405,7 @@ RegisterContextDarwin_i386::RegisterContextDarwin_i386( } } -RegisterContextDarwin_i386::~RegisterContextDarwin_i386() {} +RegisterContextDarwin_i386::~RegisterContextDarwin_i386() = default; void RegisterContextDarwin_i386::InvalidateAllRegisters() { InvalidateAllRegisterStates(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 38cd00aea9cc..03e5ea424e39 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// -#include <inttypes.h> -#include <stdarg.h> -#include <stddef.h> +#include <cinttypes> +#include <cstdarg> +#include <cstddef> #include <memory> @@ -467,7 +467,7 @@ RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64( } } -RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() {} +RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() = default; void RegisterContextDarwin_x86_64::InvalidateAllRegisters() { InvalidateAllRegisterStates(); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp index 9fe6255d698e..2991bd3c5f2c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp @@ -178,7 +178,7 @@ RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc( const ArchSpec &target_arch) : RegisterInfoInterface(target_arch) {} -RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() {} +RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc() = default; size_t RegisterContextFreeBSD_powerpc::GetGPRSize() const { // This is an 'abstract' base, so no GPR struct. @@ -197,7 +197,7 @@ RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32( const ArchSpec &target_arch) : RegisterContextFreeBSD_powerpc(target_arch) {} -RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() {} +RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32() = default; size_t RegisterContextFreeBSD_powerpc32::GetGPRSize() const { return sizeof(GPR32); @@ -217,7 +217,7 @@ RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64( const ArchSpec &target_arch) : RegisterContextFreeBSD_powerpc(target_arch) {} -RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() {} +RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64() = default; size_t RegisterContextFreeBSD_powerpc64::GetGPRSize() const { return sizeof(GPR64); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp deleted file mode 100644 index 837549e2a495..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ /dev/null @@ -1,149 +0,0 @@ -//===-- RegisterContextLinux_mips.cpp -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - -#include <stddef.h> -#include <vector> - -// For eh_frame and DWARF Register numbers -#include "RegisterContextLinux_mips.h" - -// Internal codes for mips registers -#include "lldb-mips-linux-register-enums.h" - -// For GP and FP buffers -#include "RegisterContext_mips.h" - -using namespace lldb_private; -using namespace lldb; - -// Include RegisterInfos_mips to declare our g_register_infos_mips structure. -#define DECLARE_REGISTER_INFOS_MIPS_STRUCT -#include "RegisterInfos_mips.h" -#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT - -// mips general purpose registers. -const uint32_t g_gp_regnums_mips[] = { - gpr_zero_mips, gpr_r1_mips, gpr_r2_mips, gpr_r3_mips, - gpr_r4_mips, gpr_r5_mips, gpr_r6_mips, gpr_r7_mips, - gpr_r8_mips, gpr_r9_mips, gpr_r10_mips, gpr_r11_mips, - gpr_r12_mips, gpr_r13_mips, gpr_r14_mips, gpr_r15_mips, - gpr_r16_mips, gpr_r17_mips, gpr_r18_mips, gpr_r19_mips, - gpr_r20_mips, gpr_r21_mips, gpr_r22_mips, gpr_r23_mips, - gpr_r24_mips, gpr_r25_mips, gpr_r26_mips, gpr_r27_mips, - gpr_gp_mips, gpr_sp_mips, gpr_r30_mips, gpr_ra_mips, - gpr_sr_mips, gpr_mullo_mips, gpr_mulhi_mips, gpr_badvaddr_mips, - gpr_cause_mips, gpr_pc_mips, gpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_gp_regnums_mips) / sizeof(g_gp_regnums_mips[0])) - 1 == - k_num_gpr_registers_mips, - "g_gp_regnums_mips has wrong number of register infos"); -// mips floating point registers. -const uint32_t g_fp_regnums_mips[] = { - fpr_f0_mips, fpr_f1_mips, fpr_f2_mips, fpr_f3_mips, - fpr_f4_mips, fpr_f5_mips, fpr_f6_mips, fpr_f7_mips, - fpr_f8_mips, fpr_f9_mips, fpr_f10_mips, fpr_f11_mips, - fpr_f12_mips, fpr_f13_mips, fpr_f14_mips, fpr_f15_mips, - fpr_f16_mips, fpr_f17_mips, fpr_f18_mips, fpr_f19_mips, - fpr_f20_mips, fpr_f21_mips, fpr_f22_mips, fpr_f23_mips, - fpr_f24_mips, fpr_f25_mips, fpr_f26_mips, fpr_f27_mips, - fpr_f28_mips, fpr_f29_mips, fpr_f30_mips, fpr_f31_mips, - fpr_fcsr_mips, fpr_fir_mips, fpr_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_fp_regnums_mips) / sizeof(g_fp_regnums_mips[0])) - 1 == - k_num_fpr_registers_mips, - "g_fp_regnums_mips has wrong number of register infos"); - -// mips MSA registers. -const uint32_t g_msa_regnums_mips[] = { - msa_w0_mips, msa_w1_mips, msa_w2_mips, msa_w3_mips, - msa_w4_mips, msa_w5_mips, msa_w6_mips, msa_w7_mips, - msa_w8_mips, msa_w9_mips, msa_w10_mips, msa_w11_mips, - msa_w12_mips, msa_w13_mips, msa_w14_mips, msa_w15_mips, - msa_w16_mips, msa_w17_mips, msa_w18_mips, msa_w19_mips, - msa_w20_mips, msa_w21_mips, msa_w22_mips, msa_w23_mips, - msa_w24_mips, msa_w25_mips, msa_w26_mips, msa_w27_mips, - msa_w28_mips, msa_w29_mips, msa_w30_mips, msa_w31_mips, - msa_fcsr_mips, msa_fir_mips, msa_mcsr_mips, msa_mir_mips, - msa_config5_mips, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_msa_regnums_mips) / sizeof(g_msa_regnums_mips[0])) - - 1 == - k_num_msa_registers_mips, - "g_msa_regnums_mips has wrong number of register infos"); - -// Number of register sets provided by this context. -constexpr size_t k_num_register_sets = 3; - -// Register sets for mips. -static const RegisterSet g_reg_sets_mips[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_mips, - g_gp_regnums_mips}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_mips, - g_fp_regnums_mips}, - {"MSA Registers", "msa", k_num_msa_registers_mips, g_msa_regnums_mips}}; - -uint32_t GetUserRegisterInfoCount(bool msa_present) { - if (msa_present) - return static_cast<uint32_t>(k_num_user_registers_mips); - return static_cast<uint32_t>(k_num_user_registers_mips - - k_num_msa_registers_mips); -} - -RegisterContextLinux_mips::RegisterContextLinux_mips( - const ArchSpec &target_arch, bool msa_present) - : RegisterInfoInterface(target_arch), - m_user_register_count(GetUserRegisterInfoCount(msa_present)) {} - -size_t RegisterContextLinux_mips::GetGPRSize() const { - return sizeof(GPR_linux_mips); -} - -const RegisterInfo *RegisterContextLinux_mips::GetRegisterInfo() const { - switch (m_target_arch.GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return g_register_infos_mips; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } -} - -const RegisterSet * -RegisterContextLinux_mips::GetRegisterSet(size_t set) const { - if (set >= k_num_register_sets) - return nullptr; - switch (m_target_arch.GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return &g_reg_sets_mips[set]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } -} - -size_t -RegisterContextLinux_mips::GetRegisterSetCount() const { - return k_num_register_sets; -} - -uint32_t RegisterContextLinux_mips::GetRegisterCount() const { - return static_cast<uint32_t>(sizeof(g_register_infos_mips) / - sizeof(g_register_infos_mips[0])); -} - -uint32_t RegisterContextLinux_mips::GetUserRegisterCount() const { - return static_cast<uint32_t>(m_user_register_count); -} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h deleted file mode 100644 index 9b59ab421ff4..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- RegisterContextLinux_mips.h ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H -#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS_H - -#include "RegisterInfoInterface.h" -#include "lldb/lldb-private.h" - -class RegisterContextLinux_mips : public lldb_private::RegisterInfoInterface { -public: - RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, - bool msa_present = true); - - size_t GetGPRSize() const override; - - const lldb_private::RegisterInfo *GetRegisterInfo() const override; - - const lldb_private::RegisterSet *GetRegisterSet(size_t set) const; - - size_t GetRegisterSetCount() const; - - uint32_t GetRegisterCount() const override; - - uint32_t GetUserRegisterCount() const override; - -private: - uint32_t m_user_register_count; -}; - -#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp deleted file mode 100644 index 432a78129fde..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ /dev/null @@ -1,207 +0,0 @@ -//===-- RegisterContextLinux_mips64.cpp -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - - -#include <stddef.h> -#include <vector> - -// For eh_frame and DWARF Register numbers -#include "RegisterContextLinux_mips64.h" - -// For GP and FP buffers -#include "RegisterContext_mips.h" - -// Internal codes for all mips32 and mips64 registers -#include "lldb-mips-linux-register-enums.h" - -using namespace lldb; -using namespace lldb_private; - -// Include RegisterInfos_mips64 to declare our g_register_infos_mips64 -// structure. -#define DECLARE_REGISTER_INFOS_MIPS64_STRUCT -#define LINUX_MIPS64 -#include "RegisterInfos_mips64.h" -#undef LINUX_MIPS64 -#undef DECLARE_REGISTER_INFOS_MIPS64_STRUCT - -// Include RegisterInfos_mips to declare our g_register_infos_mips structure. -#define DECLARE_REGISTER_INFOS_MIPS_STRUCT -#include "RegisterInfos_mips.h" -#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT - -// mips64 general purpose registers. -const uint32_t g_gp_regnums_mips64[] = { - gpr_zero_mips64, gpr_r1_mips64, gpr_r2_mips64, - gpr_r3_mips64, gpr_r4_mips64, gpr_r5_mips64, - gpr_r6_mips64, gpr_r7_mips64, gpr_r8_mips64, - gpr_r9_mips64, gpr_r10_mips64, gpr_r11_mips64, - gpr_r12_mips64, gpr_r13_mips64, gpr_r14_mips64, - gpr_r15_mips64, gpr_r16_mips64, gpr_r17_mips64, - gpr_r18_mips64, gpr_r19_mips64, gpr_r20_mips64, - gpr_r21_mips64, gpr_r22_mips64, gpr_r23_mips64, - gpr_r24_mips64, gpr_r25_mips64, gpr_r26_mips64, - gpr_r27_mips64, gpr_gp_mips64, gpr_sp_mips64, - gpr_r30_mips64, gpr_ra_mips64, gpr_sr_mips64, - gpr_mullo_mips64, gpr_mulhi_mips64, gpr_badvaddr_mips64, - gpr_cause_mips64, gpr_pc_mips64, gpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_gp_regnums_mips64) / sizeof(g_gp_regnums_mips64[0])) - - 1 == - k_num_gpr_registers_mips64, - "g_gp_regnums_mips64 has wrong number of register infos"); - -// mips64 floating point registers. -const uint32_t g_fp_regnums_mips64[] = { - fpr_f0_mips64, fpr_f1_mips64, fpr_f2_mips64, fpr_f3_mips64, - fpr_f4_mips64, fpr_f5_mips64, fpr_f6_mips64, fpr_f7_mips64, - fpr_f8_mips64, fpr_f9_mips64, fpr_f10_mips64, fpr_f11_mips64, - fpr_f12_mips64, fpr_f13_mips64, fpr_f14_mips64, fpr_f15_mips64, - fpr_f16_mips64, fpr_f17_mips64, fpr_f18_mips64, fpr_f19_mips64, - fpr_f20_mips64, fpr_f21_mips64, fpr_f22_mips64, fpr_f23_mips64, - fpr_f24_mips64, fpr_f25_mips64, fpr_f26_mips64, fpr_f27_mips64, - fpr_f28_mips64, fpr_f29_mips64, fpr_f30_mips64, fpr_f31_mips64, - fpr_fcsr_mips64, fpr_fir_mips64, fpr_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_fp_regnums_mips64) / sizeof(g_fp_regnums_mips64[0])) - - 1 == - k_num_fpr_registers_mips64, - "g_fp_regnums_mips64 has wrong number of register infos"); - -// mips64 MSA registers. -const uint32_t g_msa_regnums_mips64[] = { - msa_w0_mips64, msa_w1_mips64, msa_w2_mips64, msa_w3_mips64, - msa_w4_mips64, msa_w5_mips64, msa_w6_mips64, msa_w7_mips64, - msa_w8_mips64, msa_w9_mips64, msa_w10_mips64, msa_w11_mips64, - msa_w12_mips64, msa_w13_mips64, msa_w14_mips64, msa_w15_mips64, - msa_w16_mips64, msa_w17_mips64, msa_w18_mips64, msa_w19_mips64, - msa_w20_mips64, msa_w21_mips64, msa_w22_mips64, msa_w23_mips64, - msa_w24_mips64, msa_w25_mips64, msa_w26_mips64, msa_w27_mips64, - msa_w28_mips64, msa_w29_mips64, msa_w30_mips64, msa_w31_mips64, - msa_fcsr_mips64, msa_fir_mips64, msa_mcsr_mips64, msa_mir_mips64, - msa_config5_mips64, - LLDB_INVALID_REGNUM // register sets need to end with this flag -}; - -static_assert((sizeof(g_msa_regnums_mips64) / sizeof(g_msa_regnums_mips64[0])) - - 1 == - k_num_msa_registers_mips64, - "g_msa_regnums_mips64 has wrong number of register infos"); - -// Number of register sets provided by this context. -constexpr size_t k_num_register_sets = 3; - -// Register sets for mips64. -static const RegisterSet g_reg_sets_mips64[k_num_register_sets] = { - {"General Purpose Registers", "gpr", k_num_gpr_registers_mips64, - g_gp_regnums_mips64}, - {"Floating Point Registers", "fpu", k_num_fpr_registers_mips64, - g_fp_regnums_mips64}, - {"MSA Registers", "msa", k_num_msa_registers_mips64, g_msa_regnums_mips64}, -}; - -const RegisterSet * -RegisterContextLinux_mips64::GetRegisterSet(size_t set) const { - if (set >= k_num_register_sets) - return nullptr; - - switch (m_target_arch.GetMachine()) { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return &g_reg_sets_mips64[set]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } - return nullptr; -} - -size_t -RegisterContextLinux_mips64::GetRegisterSetCount() const { - return k_num_register_sets; -} - -static const RegisterInfo *GetRegisterInfoPtr(const ArchSpec &target_arch) { - switch (target_arch.GetMachine()) { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return g_register_infos_mips64; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return g_register_infos_mips; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } -} - -static uint32_t GetRegisterInfoCount(const ArchSpec &target_arch) { - switch (target_arch.GetMachine()) { - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - return static_cast<uint32_t>(sizeof(g_register_infos_mips64) / - sizeof(g_register_infos_mips64[0])); - case llvm::Triple::mips: - case llvm::Triple::mipsel: - return static_cast<uint32_t>(sizeof(g_register_infos_mips) / - sizeof(g_register_infos_mips[0])); - default: - assert(false && "Unhandled target architecture."); - return 0; - } -} - -uint32_t GetUserRegisterInfoCount(const ArchSpec &target_arch, - bool msa_present) { - switch (target_arch.GetMachine()) { - case llvm::Triple::mips: - case llvm::Triple::mipsel: - if (msa_present) - return static_cast<uint32_t>(k_num_user_registers_mips); - return static_cast<uint32_t>(k_num_user_registers_mips - - k_num_msa_registers_mips); - case llvm::Triple::mips64el: - case llvm::Triple::mips64: - if (msa_present) - return static_cast<uint32_t>(k_num_user_registers_mips64); - return static_cast<uint32_t>(k_num_user_registers_mips64 - - k_num_msa_registers_mips64); - default: - assert(false && "Unhandled target architecture."); - return 0; - } -} - -RegisterContextLinux_mips64::RegisterContextLinux_mips64( - const ArchSpec &target_arch, bool msa_present) - : lldb_private::RegisterInfoInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)), - m_user_register_count( - GetUserRegisterInfoCount(target_arch, msa_present)) {} - -size_t RegisterContextLinux_mips64::GetGPRSize() const { - return sizeof(GPR_linux_mips); -} - -const RegisterInfo *RegisterContextLinux_mips64::GetRegisterInfo() const { - return m_register_info_p; -} - -uint32_t RegisterContextLinux_mips64::GetRegisterCount() const { - return m_register_info_count; -} - -uint32_t RegisterContextLinux_mips64::GetUserRegisterCount() const { - return m_user_register_count; -} - diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h deleted file mode 100644 index 899f0a40e4ae..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ /dev/null @@ -1,39 +0,0 @@ -//===-- RegisterContextLinux_mips64.h ---------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H -#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTLINUX_MIPS64_H - -#include "RegisterInfoInterface.h" -#include "lldb/lldb-private.h" - -class RegisterContextLinux_mips64 : public lldb_private::RegisterInfoInterface { -public: - RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, - bool msa_present = true); - - size_t GetGPRSize() const override; - - const lldb_private::RegisterInfo *GetRegisterInfo() const override; - - const lldb_private::RegisterSet *GetRegisterSet(size_t set) const; - - size_t GetRegisterSetCount() const; - - uint32_t GetRegisterCount() const override; - - uint32_t GetUserRegisterCount() const override; - -private: - const lldb_private::RegisterInfo *m_register_info_p; - uint32_t m_register_info_count; - uint32_t m_user_register_count; -}; - -#endif - diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp index 1394cb7f00a1..067d1c3705e4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp @@ -21,7 +21,7 @@ RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, uint32_t concrete_frame_idx) : RegisterContextDarwin_arm(thread, concrete_frame_idx) {} -RegisterContextMach_arm::~RegisterContextMach_arm() {} +RegisterContextMach_arm::~RegisterContextMach_arm() = default; int RegisterContextMach_arm::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { mach_msg_type_number_t count = GPRWordCount; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp index b97166b6eebe..fe5cecef1b0c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp @@ -19,7 +19,7 @@ RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread, uint32_t concrete_frame_idx) : RegisterContextDarwin_i386(thread, concrete_frame_idx) {} -RegisterContextMach_i386::~RegisterContextMach_i386() {} +RegisterContextMach_i386::~RegisterContextMach_i386() = default; int RegisterContextMach_i386::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { mach_msg_type_number_t count = GPRWordCount; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp index 8933f136789f..a3d8c4f649d2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp @@ -19,7 +19,7 @@ RegisterContextMach_x86_64::RegisterContextMach_x86_64( Thread &thread, uint32_t concrete_frame_idx) : RegisterContextDarwin_x86_64(thread, concrete_frame_idx) {} -RegisterContextMach_x86_64::~RegisterContextMach_x86_64() {} +RegisterContextMach_x86_64::~RegisterContextMach_x86_64() = default; int RegisterContextMach_x86_64::DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp index f2d230b54053..c55ffebb03e7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextMemory.cpp @@ -39,7 +39,7 @@ RegisterContextMemory::RegisterContextMemory(Thread &thread, } // Destructor -RegisterContextMemory::~RegisterContextMemory() {} +RegisterContextMemory::~RegisterContextMemory() = default; void RegisterContextMemory::InvalidateAllRegisters() { if (m_reg_data_addr != LLDB_INVALID_ADDRESS) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index 97a760396ba9..684176bccdf0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -45,7 +45,7 @@ RegisterContextPOSIX_arm::RegisterContextPOSIX_arm( : lldb_private::RegisterContext(thread, 0), m_register_info_up(std::move(register_info)) {} -RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {} +RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() = default; void RegisterContextPOSIX_arm::Invalidate() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 3f52501c35f3..676e450c4846 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -40,10 +40,11 @@ bool RegisterContextPOSIX_arm64::IsFPR(unsigned reg) { } bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const { - if (m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == - RegisterInfoPOSIX_arm64::SVERegSet) - return true; - return false; + return m_register_info_up->IsSVEReg(reg); +} + +bool RegisterContextPOSIX_arm64::IsPAuth(unsigned reg) const { + return m_register_info_up->IsPAuthReg(reg); } RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( @@ -52,7 +53,7 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( : lldb_private::RegisterContext(thread, 0), m_register_info_up(std::move(register_info)) {} -RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {} +RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() = default; void RegisterContextPOSIX_arm64::Invalidate() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index a3f07bb2823b..7c301599d3af 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -54,6 +54,7 @@ protected: size_t GetFPUSize() { return sizeof(RegisterInfoPOSIX_arm64::FPU); } bool IsSVE(unsigned reg) const; + bool IsPAuth(unsigned reg) const; bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); } bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp index c41c4bd7a7ea..9e05737d8e62 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -22,8 +22,6 @@ #include "RegisterContextPOSIX_mips64.h" #include "RegisterContextFreeBSD_mips64.h" -#include "RegisterContextLinux_mips64.h" -#include "RegisterContextLinux_mips.h" using namespace lldb_private; using namespace lldb; @@ -60,7 +58,7 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64( m_registers_count[msa_registers_count])); } -RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {} +RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() = default; void RegisterContextPOSIX_mips64::Invalidate() {} @@ -102,17 +100,6 @@ RegisterContextPOSIX_mips64::GetRegisterInfoAtIndex(size_t reg) { size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { ArchSpec target_arch = m_register_info_up->GetTargetArchitecture(); switch (target_arch.GetTriple().getOS()) { - case llvm::Triple::Linux: { - if ((target_arch.GetMachine() == llvm::Triple::mipsel) || - (target_arch.GetMachine() == llvm::Triple::mips)) { - const auto *context = static_cast<const RegisterContextLinux_mips *>( - m_register_info_up.get()); - return context->GetRegisterSetCount(); - } - const auto *context = static_cast<const RegisterContextLinux_mips64 *>( - m_register_info_up.get()); - return context->GetRegisterSetCount(); - } default: { const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>( m_register_info_up.get()); @@ -125,17 +112,6 @@ size_t RegisterContextPOSIX_mips64::GetRegisterSetCount() { const RegisterSet *RegisterContextPOSIX_mips64::GetRegisterSet(size_t set) { ArchSpec target_arch = m_register_info_up->GetTargetArchitecture(); switch (target_arch.GetTriple().getOS()) { - case llvm::Triple::Linux: { - if ((target_arch.GetMachine() == llvm::Triple::mipsel) || - (target_arch.GetMachine() == llvm::Triple::mips)) { - const auto *context = static_cast<const RegisterContextLinux_mips *>( - m_register_info_up.get()); - return context->GetRegisterSet(set); - } - const auto *context = static_cast<const RegisterContextLinux_mips64 *>( - m_register_info_up.get()); - return context->GetRegisterSet(set); - } default: { const auto *context = static_cast<const RegisterContextFreeBSD_mips64 *>( m_register_info_up.get()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp index cd65b96d373e..cffd2865e385 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -95,7 +95,7 @@ RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc( m_register_info_up.reset(register_info); } -RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {} +RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() = default; void RegisterContextPOSIX_powerpc::Invalidate() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp index f670be2ef3c4..f70ddeba209c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp index e746ec642b38..21c8160e5b41 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -98,7 +98,7 @@ RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x( } } -RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() {} +RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() = default; void RegisterContextPOSIX_s390x::Invalidate() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 2c7f63503d7c..67e03ff1ea39 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// +#include <cerrno> +#include <cstdint> #include <cstring> -#include <errno.h> -#include <stdint.h> #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -448,7 +448,7 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( m_fpr_type = eNotValid; } -RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() {} +RegisterContextPOSIX_x86::~RegisterContextPOSIX_x86() = default; RegisterContextPOSIX_x86::FPRType RegisterContextPOSIX_x86::GetFPRType() { if (m_fpr_type == eNotValid) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp index 31e2944084ed..4866cbd235e8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp @@ -22,7 +22,7 @@ RegisterContextThreadMemory::RegisterContextThreadMemory( : RegisterContext(thread, 0), m_thread_wp(thread.shared_from_this()), m_reg_ctx_sp(), m_register_data_addr(register_data_addr), m_stop_id(0) {} -RegisterContextThreadMemory::~RegisterContextThreadMemory() {} +RegisterContextThreadMemory::~RegisterContextThreadMemory() = default; void RegisterContextThreadMemory::UpdateRegisterContext() { ThreadSP thread_sp(m_thread_wp.lock()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h index 88c2ae7c5010..c05438338c88 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -22,7 +22,7 @@ class RegisterInfoInterface { public: RegisterInfoInterface(const lldb_private::ArchSpec &target_arch) : m_target_arch(target_arch) {} - virtual ~RegisterInfoInterface() {} + virtual ~RegisterInfoInterface() = default; virtual size_t GetGPRSize() const = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp index 17b96f944cda..63461f7ab2db 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp @@ -7,7 +7,7 @@ //===---------------------------------------------------------------------===// #include <cassert> -#include <stddef.h> +#include <cstddef> #include <vector> #include "lldb/lldb-defines.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 515c9f44e1e2..b878534b39db 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -7,7 +7,7 @@ //===---------------------------------------------------------------------===// #include <cassert> -#include <stddef.h> +#include <cstddef> #include <vector> #include "lldb/lldb-defines.h" @@ -72,23 +72,14 @@ #include "RegisterInfos_arm64_sve.h" #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT -static const lldb_private::RegisterInfo * -GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { - switch (target_arch.GetMachine()) { - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - return g_register_infos_arm64_le; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } -} - // Number of register sets provided by this context. enum { k_num_gpr_registers = gpr_w28 - gpr_x0 + 1, k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1, k_num_sve_registers = sve_ffr - sve_vg + 1, + k_num_mte_register = 1, + k_num_pauth_register = 2, + k_num_register_sets_default = 2, k_num_register_sets = 3 }; @@ -186,31 +177,66 @@ static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = { {"Scalable Vector Extension Registers", "sve", k_num_sve_registers, g_sve_regnums_arm64}}; -static uint32_t -GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) { +static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = { + "Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL}; + +static const lldb_private::RegisterSet g_reg_set_mte_arm64 = { + "MTE Control Register", "mte", k_num_mte_register, NULL}; + +RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( + const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets) + : lldb_private::RegisterInfoAndSetInterface(target_arch), + m_opt_regsets(opt_regsets) { switch (target_arch.GetMachine()) { case llvm::Triple::aarch64: - case llvm::Triple::aarch64_32: - return static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) / - sizeof(g_register_infos_arm64_le[0])); + case llvm::Triple::aarch64_32: { + m_register_set_p = g_reg_sets_arm64; + m_register_set_count = k_num_register_sets_default; + m_per_regset_regnum_range[GPRegSet] = std::make_pair(gpr_x0, gpr_w28 + 1); + m_per_regset_regnum_range[FPRegSet] = std::make_pair(fpu_v0, fpu_fpcr + 1); + + // Now configure register sets supported by current target. If we have a + // dynamic register set like MTE, Pointer Authentication regset then we need + // to create dynamic register infos and regset array. Push back all optional + // register infos and regset and calculate register offsets accordingly. + if (m_opt_regsets.AllSet(eRegsetMaskSVE)) { + m_register_info_p = g_register_infos_arm64_sve_le; + m_register_info_count = sve_ffr + 1; + m_per_regset_regnum_range[m_register_set_count++] = + std::make_pair(sve_vg, sve_ffr + 1); + } else { + m_register_info_p = g_register_infos_arm64_le; + m_register_info_count = fpu_fpcr + 1; + } + + if (m_opt_regsets.AnySet(eRegsetMaskDynamic)) { + llvm::ArrayRef<lldb_private::RegisterInfo> reg_infos_ref = + llvm::makeArrayRef(m_register_info_p, m_register_info_count); + llvm::ArrayRef<lldb_private::RegisterSet> reg_sets_ref = + llvm::makeArrayRef(m_register_set_p, m_register_set_count); + llvm::copy(reg_infos_ref, std::back_inserter(m_dynamic_reg_infos)); + llvm::copy(reg_sets_ref, std::back_inserter(m_dynamic_reg_sets)); + + if (m_opt_regsets.AllSet(eRegsetMaskPAuth)) + AddRegSetPAuth(); + + if (m_opt_regsets.AllSet(eRegsetMaskMTE)) + AddRegSetMTE(); + + m_register_info_count = m_dynamic_reg_infos.size(); + m_register_info_p = m_dynamic_reg_infos.data(); + m_register_set_p = m_dynamic_reg_sets.data(); + m_register_set_count = m_dynamic_reg_sets.size(); + } + break; + } default: assert(false && "Unhandled target architecture."); - return 0; } } -RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( - const lldb_private::ArchSpec &target_arch) - : lldb_private::RegisterInfoAndSetInterface(target_arch), - m_register_info_p(GetRegisterInfoPtr(target_arch)), - m_register_info_count(GetRegisterInfoCount(target_arch)) { -} - uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { - if (IsSVEEnabled()) - return k_num_gpr_registers + k_num_fpr_registers + k_num_sve_registers; - - return k_num_gpr_registers + k_num_fpr_registers; + return m_register_info_count; } size_t RegisterInfoPOSIX_arm64::GetGPRSize() const { @@ -227,31 +253,60 @@ RegisterInfoPOSIX_arm64::GetRegisterInfo() const { } size_t RegisterInfoPOSIX_arm64::GetRegisterSetCount() const { - if (IsSVEEnabled()) - return k_num_register_sets; - return k_num_register_sets - 1; + return m_register_set_count; } size_t RegisterInfoPOSIX_arm64::GetRegisterSetFromRegisterIndex( uint32_t reg_index) const { - if (reg_index <= gpr_w28) - return GPRegSet; - if (reg_index <= fpu_fpcr) - return FPRegSet; - if (reg_index <= sve_ffr) - return SVERegSet; + for (const auto ®set_range : m_per_regset_regnum_range) { + if (reg_index >= regset_range.second.first && + reg_index < regset_range.second.second) + return regset_range.first; + } return LLDB_INVALID_REGNUM; } const lldb_private::RegisterSet * RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const { if (set_index < GetRegisterSetCount()) - return &g_reg_sets_arm64[set_index]; + return &m_register_set_p[set_index]; return nullptr; } -uint32_t -RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) { +void RegisterInfoPOSIX_arm64::AddRegSetPAuth() { + uint32_t pa_regnum = m_dynamic_reg_infos.size(); + for (uint32_t i = 0; i < k_num_pauth_register; i++) { + pauth_regnum_collection.push_back(pa_regnum + i); + m_dynamic_reg_infos.push_back(g_register_infos_pauth[i]); + m_dynamic_reg_infos[pa_regnum + i].byte_offset = + m_dynamic_reg_infos[pa_regnum + i - 1].byte_offset + + m_dynamic_reg_infos[pa_regnum + i - 1].byte_size; + m_dynamic_reg_infos[pa_regnum + i].kinds[lldb::eRegisterKindLLDB] = + pa_regnum + i; + } + + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(pa_regnum, m_dynamic_reg_infos.size()); + m_dynamic_reg_sets.push_back(g_reg_set_pauth_arm64); + m_dynamic_reg_sets.back().registers = pauth_regnum_collection.data(); +} + +void RegisterInfoPOSIX_arm64::AddRegSetMTE() { + uint32_t mte_regnum = m_dynamic_reg_infos.size(); + m_mte_regnum_collection.push_back(mte_regnum); + m_dynamic_reg_infos.push_back(g_register_infos_mte[0]); + m_dynamic_reg_infos[mte_regnum].byte_offset = + m_dynamic_reg_infos[mte_regnum - 1].byte_offset + + m_dynamic_reg_infos[mte_regnum - 1].byte_size; + m_dynamic_reg_infos[mte_regnum].kinds[lldb::eRegisterKindLLDB] = mte_regnum; + + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(mte_regnum, mte_regnum + 1); + m_dynamic_reg_sets.push_back(g_reg_set_mte_arm64); + m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data(); +} + +uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) { // sve_vq contains SVE Quad vector length in context of AArch64 SVE. // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0. // Also if an invalid or previously set vector length is passed to this @@ -266,28 +321,15 @@ RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) { m_vector_reg_vq = sve_vq; - if (sve_vq == eVectorQuadwordAArch64) { - m_register_info_count = - static_cast<uint32_t>(sizeof(g_register_infos_arm64_le) / - sizeof(g_register_infos_arm64_le[0])); - m_register_info_p = g_register_infos_arm64_le; - + if (sve_vq == eVectorQuadwordAArch64) return m_vector_reg_vq; - } - - m_register_info_count = - static_cast<uint32_t>(sizeof(g_register_infos_arm64_sve_le) / - sizeof(g_register_infos_arm64_sve_le[0])); - std::vector<lldb_private::RegisterInfo> ®_info_ref = m_per_vq_reg_infos[sve_vq]; if (reg_info_ref.empty()) { - reg_info_ref = llvm::makeArrayRef(g_register_infos_arm64_sve_le, - m_register_info_count); + reg_info_ref = llvm::makeArrayRef(m_register_info_p, m_register_info_count); uint32_t offset = SVE_REGS_DEFAULT_OFFSET_LINUX; - reg_info_ref[fpu_fpsr].byte_offset = offset; reg_info_ref[fpu_fpcr].byte_offset = offset + 4; reg_info_ref[sve_vg].byte_offset = offset + 8; @@ -316,13 +358,25 @@ RegisterInfoPOSIX_arm64::ConfigureVectorRegisterInfos(uint32_t sve_vq) { offset += reg_info_ref[it].byte_size; } + for (uint32_t it = sve_ffr + 1; it < m_register_info_count; it++) { + reg_info_ref[it].byte_offset = offset; + offset += reg_info_ref[it].byte_size; + } + m_per_vq_reg_infos[sve_vq] = reg_info_ref; } - m_register_info_p = reg_info_ref.data(); + m_register_info_p = m_per_vq_reg_infos[sve_vq].data(); return m_vector_reg_vq; } +bool RegisterInfoPOSIX_arm64::IsSVEReg(unsigned reg) const { + if (m_vector_reg_vq > eVectorQuadwordAArch64) + return (sve_vg <= reg && reg <= sve_ffr); + else + return false; +} + bool RegisterInfoPOSIX_arm64::IsSVEZReg(unsigned reg) const { return (sve_z0 <= reg && reg <= sve_z31); } @@ -335,6 +389,18 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const { return sve_vg == reg; } +bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const { + return std::find(pauth_regnum_collection.begin(), + pauth_regnum_collection.end(), + reg) != pauth_regnum_collection.end(); +} + +bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const { + return std::find(m_mte_regnum_collection.begin(), + m_mte_regnum_collection.end(), + reg) != m_mte_regnum_collection.end(); +} + uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; } @@ -344,3 +410,11 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPCR() const { return fpu_fpcr; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; } + +uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const { + return m_register_info_p[pauth_regnum_collection[0]].byte_offset; +} + +uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const { + return m_register_info_p[m_mte_regnum_collection[0]].byte_offset; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h index 2929f2009dd9..ba873ba4436b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -11,6 +11,7 @@ #include "RegisterInfoAndSetInterface.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Flags.h" #include "lldb/lldb-private.h" #include <map> @@ -19,7 +20,16 @@ enum class SVEState { Unknown, Disabled, FPSIMD, Full }; class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoAndSetInterface { public: - enum { GPRegSet = 0, FPRegSet, SVERegSet }; + enum { GPRegSet = 0, FPRegSet }; + + // AArch64 register set mask value + enum { + eRegsetMaskDefault = 0, + eRegsetMaskSVE = 1, + eRegsetMaskPAuth = 2, + eRegsetMaskMTE = 4, + eRegsetMaskDynamic = ~1, + }; // AArch64 Register set FP/SIMD feature configuration enum { @@ -68,7 +78,8 @@ public: uint64_t mdscr_el1; }; - RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch); + RegisterInfoPOSIX_arm64(const lldb_private::ArchSpec &target_arch, + lldb_private::Flags opt_regsets); size_t GetGPRSize() const override; @@ -85,7 +96,11 @@ public: size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override; - uint32_t ConfigureVectorRegisterInfos(uint32_t sve_vq); + void AddRegSetPAuth(); + + void AddRegSetMTE(); + + uint32_t ConfigureVectorLength(uint32_t sve_vq); bool VectorSizeIsValid(uint32_t vq) { if (vq >= eVectorQuadwordAArch64 && vq <= eVectorQuadwordAArch64SVEMax) @@ -93,17 +108,23 @@ public: return false; } - bool IsSVEEnabled() const { return m_vector_reg_vq > eVectorQuadwordAArch64; } + bool IsSVEEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskSVE); } + bool IsPAuthEnabled() const { return m_opt_regsets.AnySet(eRegsetMaskPAuth); } + bool IsSVEReg(unsigned reg) const; bool IsSVEZReg(unsigned reg) const; bool IsSVEPReg(unsigned reg) const; bool IsSVERegVG(unsigned reg) const; + bool IsPAuthReg(unsigned reg) const; + bool IsMTEReg(unsigned reg) const; uint32_t GetRegNumSVEZ0() const; uint32_t GetRegNumSVEFFR() const; uint32_t GetRegNumFPCR() const; uint32_t GetRegNumFPSR() const; uint32_t GetRegNumSVEVG() const; + uint32_t GetPAuthOffset() const; + uint32_t GetMTEOffset() const; private: typedef std::map<uint32_t, std::vector<lldb_private::RegisterInfo>> @@ -115,6 +136,21 @@ private: const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; + + const lldb_private::RegisterSet *m_register_set_p; + uint32_t m_register_set_count; + + // Contains pair of [start, end] register numbers of a register set with start + // and end included. + std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range; + + lldb_private::Flags m_opt_regsets; + + std::vector<lldb_private::RegisterInfo> m_dynamic_reg_infos; + std::vector<lldb_private::RegisterSet> m_dynamic_reg_sets; + + std::vector<uint32_t> pauth_regnum_collection; + std::vector<uint32_t> m_mte_regnum_collection; }; #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp index 3461d38a3901..159fd2856443 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.cpp @@ -7,7 +7,7 @@ //===---------------------------------------------------------------------===// #include <cassert> -#include <stddef.h> +#include <cstddef> #include <vector> #include "lldb/lldb-defines.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h index 74b9e3b2db32..4af0069eb6f3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm.h @@ -8,7 +8,7 @@ #ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT -#include <stddef.h> +#include <cstddef> #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 4aee55e7afba..47cedc31bcd7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -8,7 +8,7 @@ #ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT -#include <stddef.h> +#include <cstddef> #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" @@ -470,6 +470,13 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; LLDB_INVALID_REGNUM, lldb_kind \ } +// Generates register kinds array for registers with only lldb kind +#define KIND_ALL_INVALID \ + { \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM \ + } + // Generates register kinds array for vector registers #define GPR64_KIND(reg, generic_kind) MISC_KIND(reg, gpr, generic_kind) #define VREG_KIND(reg) MISC_KIND(reg, fpu, LLDB_INVALID_REGNUM) @@ -526,6 +533,13 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; nullptr, 0 \ } +// Defines pointer authentication mask registers +#define DEFINE_EXTENSION_REG(reg) \ + { \ + #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ + KIND_ALL_INVALID, nullptr, nullptr, nullptr, 0 \ + } + static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { // DEFINE_GPR64(name, GENERIC KIND) DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1), @@ -772,7 +786,12 @@ static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { {DEFINE_DBG(wcr, 13)}, {DEFINE_DBG(wcr, 14)}, {DEFINE_DBG(wcr, 15)} - // clang-format on }; +// clang-format on +static lldb_private::RegisterInfo g_register_infos_pauth[] = { + DEFINE_EXTENSION_REG(data_mask), DEFINE_EXTENSION_REG(code_mask)}; + +static lldb_private::RegisterInfo g_register_infos_mte[] = { + DEFINE_EXTENSION_REG(mte_ctrl)}; #endif // DECLARE_REGISTER_INFOS_ARM64_STRUCT diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h index 08201fd1191c..93f93d56fda2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips.h @@ -6,7 +6,7 @@ // //===---------------------------------------------------------------------===// -#include <stddef.h> +#include <cstddef> #include "lldb/Core/dwarf.h" #include "llvm/Support/Compiler.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h index b6e218ea4414..b28b91810e48 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_mips64.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stddef.h> +#include <cstddef> #include "lldb/Core/dwarf.h" #include "llvm/Support/Compiler.h" @@ -15,37 +15,11 @@ #ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT // Computes the offset of the given GPR in the user data area. -#ifdef LINUX_MIPS64 -#define GPR_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, gpr) + \ - LLVM_EXTENSION offsetof(GPR_linux_mips, regname)) -#else #define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR_freebsd_mips, regname)) -#endif - -// 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_linux_mips, regname)) - -// Computes the offset of the given MSA in the extended data area. -#define MSA_OFFSET(regname) \ - (LLVM_EXTENSION offsetof(UserArea, msa) + \ - LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB // Note that the size and offset will be updated by platform-specific classes. -#ifdef LINUX_MIPS64 -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3) \ - { \ - #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg), \ - GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, ptrace_##reg##_mips, \ - gpr_##reg##_mips64 }, \ - NULL, NULL, NULL, 0 \ - } -#else #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { \ #reg, alt, sizeof(((GPR_freebsd_mips *) 0)->reg), \ @@ -54,63 +28,10 @@ gpr_##reg##_mips64 }, \ NULL, NULL, NULL, 0 \ } -#endif - -#define DEFINE_GPR_INFO(reg, alt, kind1, kind2, kind3) \ - { \ - #reg, alt, sizeof(((GPR_linux_mips *) 0)->reg) / 2, \ - GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, ptrace_##reg##_mips, \ - gpr_##reg##_mips64 }, \ - NULL, NULL, NULL, 0 \ - } - -const uint8_t dwarf_opcode_mips64[] = { - llvm::dwarf::DW_OP_regx, dwarf_sr_mips64, llvm::dwarf::DW_OP_lit1, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shl, llvm::dwarf::DW_OP_and, - llvm::dwarf::DW_OP_lit26, llvm::dwarf::DW_OP_shr}; - -#define DEFINE_FPR(reg, alt, kind1, kind2, kind3) \ - { \ - #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \ - FPR_OFFSET(reg), eEncodingIEEE754, eFormatFloat, \ - {kind1, kind2, kind3, ptrace_##reg##_mips, \ - fpr_##reg##_mips64 }, \ - NULL, NULL, dwarf_opcode_mips64, \ - sizeof(dwarf_opcode_mips64) \ - } - -#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3) \ - { \ - #reg, alt, sizeof(((FPR_linux_mips *) 0)->reg), \ - FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, ptrace_##reg##_mips, \ - fpr_##reg##_mips64 }, \ - NULL, NULL, NULL, 0 \ - } - -#define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ - { \ - #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ - MSA_OFFSET(reg), eEncodingVector, eFormatVectorOfUInt8, \ - {kind1, kind2, kind3, kind4, \ - msa_##reg##_mips64 }, \ - NULL, NULL, NULL, 0 \ - } - -#define DEFINE_MSA_INFO(reg, alt, kind1, kind2, kind3, kind4) \ - { \ - #reg, alt, sizeof(((MSA_linux_mips *) 0)->reg), \ - MSA_OFFSET(reg), eEncodingUint, eFormatHex, \ - {kind1, kind2, kind3, kind4, \ - msa_##reg##_mips64 }, \ - NULL, NULL, NULL, 0 \ - } static RegisterInfo g_register_infos_mips64[] = { // General purpose registers. EH_Frame, DWARF, // Generic, Process Plugin -#ifndef LINUX_MIPS64 DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, @@ -191,231 +112,6 @@ static RegisterInfo g_register_infos_mips64[] = { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), -#else - DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, - LLDB_REGNUM_GENERIC_ARG1), - DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, - LLDB_REGNUM_GENERIC_ARG2), - DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, - LLDB_REGNUM_GENERIC_ARG3), - DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, - LLDB_REGNUM_GENERIC_ARG4), - DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, - LLDB_REGNUM_GENERIC_ARG5), - DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, - LLDB_REGNUM_GENERIC_ARG6), - DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, - LLDB_REGNUM_GENERIC_ARG7), - DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, - LLDB_REGNUM_GENERIC_ARG8), - DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, - LLDB_REGNUM_GENERIC_SP), - DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, - LLDB_REGNUM_GENERIC_FP), - DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, - LLDB_REGNUM_GENERIC_RA), - DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, - LLDB_REGNUM_GENERIC_FLAGS), - DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, - LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, - LLDB_REGNUM_GENERIC_PC), - DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64, - dwarf_config5_mips64, LLDB_INVALID_REGNUM), - DEFINE_FPR(f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR(f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, - LLDB_INVALID_REGNUM), - DEFINE_FPR_INFO(config5, nullptr, dwarf_config5_mips64, - dwarf_config5_mips64, LLDB_INVALID_REGNUM), - DEFINE_MSA(w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA(w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO(mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO(mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO(fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO(fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, - LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_MSA_INFO(config5, nullptr, dwarf_config5_mips64, - dwarf_config5_mips64, LLDB_INVALID_REGNUM, - LLDB_INVALID_REGNUM) -#endif }; static_assert((sizeof(g_register_infos_mips64) / diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index 90863dfdb090..04b4171b6722 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -6,7 +6,7 @@ // //===---------------------------------------------------------------------===// -#include <stddef.h> +#include <cstddef> // Computes the offset of the given GPR in the user data area. #define GPR_OFFSET(regname) (offsetof(GPR, regname)) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h index 1086d3db0b06..059dba45f9bb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64.h @@ -8,7 +8,7 @@ #ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT -#include <stddef.h> +#include <cstddef> // Computes the offset of the given GPR_PPC64 in the user data area. #define GPR_PPC64_OFFSET(regname) (offsetof(GPR_PPC64, regname)) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h index 0b099a53d875..9937da2f3050 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h @@ -8,7 +8,7 @@ #ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT -#include <stddef.h> +#include <cstddef> // Computes the offset of the given GPR in the user data area. #define GPR_OFFSET(regname) (offsetof(GPR, regname)) diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h index 11344ff8ee79..d1df7c606207 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stddef.h> +#include <cstddef> #include "llvm/Support/Compiler.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp index 2d8e8ef21612..85785a20354d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -509,7 +509,7 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( // operating system thread ID, so we can't make any assumptions about // the thread ID so we must always report the breakpoint regardless // of the thread. - if (bp_site_sp->ValidForThisThread(&thread) || + if (bp_site_sp->ValidForThisThread(thread) || thread.GetProcess()->GetOperatingSystem() != nullptr) return StopInfo::CreateStopReasonWithBreakpointSiteID( thread, bp_site_sp->GetID()); diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h b/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h deleted file mode 100644 index 348af27d2809..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/Process/Utility/lldb-mips-linux-register-enums.h +++ /dev/null @@ -1,360 +0,0 @@ -//===-- lldb-mips-linux-register-enums.h -------------------------------*- C++ -//-*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H -#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H - -namespace lldb_private { -// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) - -// Internal codes for all mips registers. -enum { - k_first_gpr_mips, - gpr_zero_mips = k_first_gpr_mips, - gpr_r1_mips, - gpr_r2_mips, - gpr_r3_mips, - gpr_r4_mips, - gpr_r5_mips, - gpr_r6_mips, - gpr_r7_mips, - gpr_r8_mips, - gpr_r9_mips, - gpr_r10_mips, - gpr_r11_mips, - gpr_r12_mips, - gpr_r13_mips, - gpr_r14_mips, - gpr_r15_mips, - gpr_r16_mips, - gpr_r17_mips, - gpr_r18_mips, - gpr_r19_mips, - gpr_r20_mips, - gpr_r21_mips, - gpr_r22_mips, - gpr_r23_mips, - gpr_r24_mips, - gpr_r25_mips, - gpr_r26_mips, - gpr_r27_mips, - gpr_gp_mips, - gpr_sp_mips, - gpr_r30_mips, - gpr_ra_mips, - gpr_sr_mips, - gpr_mullo_mips, - gpr_mulhi_mips, - gpr_badvaddr_mips, - gpr_cause_mips, - gpr_pc_mips, - gpr_config5_mips, - - k_last_gpr_mips = gpr_config5_mips, - - k_first_fpr_mips, - fpr_f0_mips = k_first_fpr_mips, - fpr_f1_mips, - fpr_f2_mips, - fpr_f3_mips, - fpr_f4_mips, - fpr_f5_mips, - fpr_f6_mips, - fpr_f7_mips, - fpr_f8_mips, - fpr_f9_mips, - fpr_f10_mips, - fpr_f11_mips, - fpr_f12_mips, - fpr_f13_mips, - fpr_f14_mips, - fpr_f15_mips, - fpr_f16_mips, - fpr_f17_mips, - fpr_f18_mips, - fpr_f19_mips, - fpr_f20_mips, - fpr_f21_mips, - fpr_f22_mips, - fpr_f23_mips, - fpr_f24_mips, - fpr_f25_mips, - fpr_f26_mips, - fpr_f27_mips, - fpr_f28_mips, - fpr_f29_mips, - fpr_f30_mips, - fpr_f31_mips, - fpr_fcsr_mips, - fpr_fir_mips, - fpr_config5_mips, - k_last_fpr_mips = fpr_config5_mips, - - k_first_msa_mips, - msa_w0_mips = k_first_msa_mips, - msa_w1_mips, - msa_w2_mips, - msa_w3_mips, - msa_w4_mips, - msa_w5_mips, - msa_w6_mips, - msa_w7_mips, - msa_w8_mips, - msa_w9_mips, - msa_w10_mips, - msa_w11_mips, - msa_w12_mips, - msa_w13_mips, - msa_w14_mips, - msa_w15_mips, - msa_w16_mips, - msa_w17_mips, - msa_w18_mips, - msa_w19_mips, - msa_w20_mips, - msa_w21_mips, - msa_w22_mips, - msa_w23_mips, - msa_w24_mips, - msa_w25_mips, - msa_w26_mips, - msa_w27_mips, - msa_w28_mips, - msa_w29_mips, - msa_w30_mips, - msa_w31_mips, - msa_fcsr_mips, - msa_fir_mips, - msa_mcsr_mips, - msa_mir_mips, - msa_config5_mips, - k_last_msa_mips = msa_config5_mips, - - k_num_registers_mips, - - k_num_gpr_registers_mips = k_last_gpr_mips - k_first_gpr_mips + 1, - k_num_fpr_registers_mips = k_last_fpr_mips - k_first_fpr_mips + 1, - k_num_msa_registers_mips = k_last_msa_mips - k_first_msa_mips + 1, - k_num_user_registers_mips = k_num_gpr_registers_mips + - k_num_fpr_registers_mips + - k_num_msa_registers_mips -}; - -// Internal codes for all mips64 registers. -enum { - k_first_gpr_mips64, - gpr_zero_mips64 = k_first_gpr_mips64, - gpr_r1_mips64, - gpr_r2_mips64, - gpr_r3_mips64, - gpr_r4_mips64, - gpr_r5_mips64, - gpr_r6_mips64, - gpr_r7_mips64, - gpr_r8_mips64, - gpr_r9_mips64, - gpr_r10_mips64, - gpr_r11_mips64, - gpr_r12_mips64, - gpr_r13_mips64, - gpr_r14_mips64, - gpr_r15_mips64, - gpr_r16_mips64, - gpr_r17_mips64, - gpr_r18_mips64, - gpr_r19_mips64, - gpr_r20_mips64, - gpr_r21_mips64, - gpr_r22_mips64, - gpr_r23_mips64, - gpr_r24_mips64, - gpr_r25_mips64, - gpr_r26_mips64, - gpr_r27_mips64, - gpr_gp_mips64, - gpr_sp_mips64, - gpr_r30_mips64, - gpr_ra_mips64, - gpr_sr_mips64, - gpr_mullo_mips64, - gpr_mulhi_mips64, - gpr_badvaddr_mips64, - gpr_cause_mips64, - gpr_pc_mips64, - gpr_config5_mips64, - k_last_gpr_mips64 = gpr_config5_mips64, - - k_first_fpr_mips64, - fpr_f0_mips64 = k_first_fpr_mips64, - fpr_f1_mips64, - fpr_f2_mips64, - fpr_f3_mips64, - fpr_f4_mips64, - fpr_f5_mips64, - fpr_f6_mips64, - fpr_f7_mips64, - fpr_f8_mips64, - fpr_f9_mips64, - fpr_f10_mips64, - fpr_f11_mips64, - fpr_f12_mips64, - fpr_f13_mips64, - fpr_f14_mips64, - fpr_f15_mips64, - fpr_f16_mips64, - fpr_f17_mips64, - fpr_f18_mips64, - fpr_f19_mips64, - fpr_f20_mips64, - fpr_f21_mips64, - fpr_f22_mips64, - fpr_f23_mips64, - fpr_f24_mips64, - fpr_f25_mips64, - fpr_f26_mips64, - fpr_f27_mips64, - fpr_f28_mips64, - fpr_f29_mips64, - fpr_f30_mips64, - fpr_f31_mips64, - fpr_fcsr_mips64, - fpr_fir_mips64, - fpr_config5_mips64, - k_last_fpr_mips64 = fpr_config5_mips64, - - k_first_msa_mips64, - msa_w0_mips64 = k_first_msa_mips64, - msa_w1_mips64, - msa_w2_mips64, - msa_w3_mips64, - msa_w4_mips64, - msa_w5_mips64, - msa_w6_mips64, - msa_w7_mips64, - msa_w8_mips64, - msa_w9_mips64, - msa_w10_mips64, - msa_w11_mips64, - msa_w12_mips64, - msa_w13_mips64, - msa_w14_mips64, - msa_w15_mips64, - msa_w16_mips64, - msa_w17_mips64, - msa_w18_mips64, - msa_w19_mips64, - msa_w20_mips64, - msa_w21_mips64, - msa_w22_mips64, - msa_w23_mips64, - msa_w24_mips64, - msa_w25_mips64, - msa_w26_mips64, - msa_w27_mips64, - msa_w28_mips64, - msa_w29_mips64, - msa_w30_mips64, - msa_w31_mips64, - msa_fcsr_mips64, - msa_fir_mips64, - msa_mcsr_mips64, - msa_mir_mips64, - msa_config5_mips64, - k_last_msa_mips64 = msa_config5_mips64, - - k_num_registers_mips64, - - k_num_gpr_registers_mips64 = k_last_gpr_mips64 - k_first_gpr_mips64 + 1, - k_num_fpr_registers_mips64 = k_last_fpr_mips64 - k_first_fpr_mips64 + 1, - k_num_msa_registers_mips64 = k_last_msa_mips64 - k_first_msa_mips64 + 1, - k_num_user_registers_mips64 = k_num_gpr_registers_mips64 + - k_num_fpr_registers_mips64 + - k_num_msa_registers_mips64 -}; - -// Register no. for RegisterKind = eRegisterKindProcessPlugin -// The ptrace request PTRACE_PEEKUSER/PTRACE_POKEUSER used this number -enum { - ptrace_zero_mips, - ptrace_r1_mips, - ptrace_r2_mips, - ptrace_r3_mips, - ptrace_r4_mips, - ptrace_r5_mips, - ptrace_r6_mips, - ptrace_r7_mips, - ptrace_r8_mips, - ptrace_r9_mips, - ptrace_r10_mips, - ptrace_r11_mips, - ptrace_r12_mips, - ptrace_r13_mips, - ptrace_r14_mips, - ptrace_r15_mips, - ptrace_r16_mips, - ptrace_r17_mips, - ptrace_r18_mips, - ptrace_r19_mips, - ptrace_r20_mips, - ptrace_r21_mips, - ptrace_r22_mips, - ptrace_r23_mips, - ptrace_r24_mips, - ptrace_r25_mips, - ptrace_r26_mips, - ptrace_r27_mips, - ptrace_gp_mips, - ptrace_sp_mips, - ptrace_r30_mips, - ptrace_ra_mips, - ptrace_f0_mips, - ptrace_f1_mips, - ptrace_f2_mips, - ptrace_f3_mips, - ptrace_f4_mips, - ptrace_f5_mips, - ptrace_f6_mips, - ptrace_f7_mips, - ptrace_f8_mips, - ptrace_f9_mips, - ptrace_f10_mips, - ptrace_f11_mips, - ptrace_f12_mips, - ptrace_f13_mips, - ptrace_f14_mips, - ptrace_f15_mips, - ptrace_f16_mips, - ptrace_f17_mips, - ptrace_f18_mips, - ptrace_f19_mips, - ptrace_f20_mips, - ptrace_f21_mips, - ptrace_f22_mips, - ptrace_f23_mips, - ptrace_f24_mips, - ptrace_f25_mips, - ptrace_f26_mips, - ptrace_f27_mips, - ptrace_f28_mips, - ptrace_f29_mips, - ptrace_f30_mips, - ptrace_f31_mips, - ptrace_pc_mips, - ptrace_cause_mips, - ptrace_badvaddr_mips, - ptrace_mulhi_mips, - ptrace_mullo_mips, - ptrace_fcsr_mips, - ptrace_fir_mips, - ptrace_sr_mips, - ptrace_config5_mips -}; -} - -#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_MIPS_LINUX_REGISTER_ENUMS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index ae19367ca3ae..12bc7390c729 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stdlib.h> +#include <cstdlib> #include <memory> #include <mutex> @@ -353,7 +353,6 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, const lldb::addr_t file_end = address_range->data.GetRangeEnd(); size_t bytes_to_read = size; // Number of bytes to read from the core file size_t bytes_copied = 0; // Number of bytes actually read from the core file - size_t zero_fill_size = 0; // Padding lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address @@ -367,24 +366,15 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, if (file_end > file_start + offset) bytes_left = file_end - (file_start + offset); - // Figure out how many bytes we need to zero-fill if we are reading more - // bytes than available in the on-disk segment - if (bytes_to_read > bytes_left) { - zero_fill_size = bytes_to_read - bytes_left; + if (bytes_to_read > bytes_left) bytes_to_read = bytes_left; - } // If there is data available on the core file read it if (bytes_to_read) bytes_copied = core_objfile->CopyData(offset + file_start, bytes_to_read, buf); - assert(zero_fill_size <= size); - // Pad remaining bytes - if (zero_fill_size) - memset(((char *)buf) + bytes_copied, 0, zero_fill_size); - - return bytes_copied + zero_fill_size; + return bytes_copied; } void ProcessElfCore::Clear() { @@ -414,12 +404,8 @@ lldb::addr_t ProcessElfCore::GetImageInfoAddress() { // Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, const DataExtractor &data, - const ArchSpec &arch) { + bool lp64) { lldb::offset_t offset = 0; - bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || - arch.GetMachine() == llvm::Triple::mips64 || - arch.GetMachine() == llvm::Triple::ppc64 || - arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -443,6 +429,27 @@ static void ParseFreeBSDPrStatus(ThreadData &thread_data, thread_data.gpregset = DataExtractor(data, offset, len); } +// Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details. +static void ParseFreeBSDPrPsInfo(ProcessElfCore &process, + const DataExtractor &data, + bool lp64) { + lldb::offset_t offset = 0; + int pr_version = data.GetU32(&offset); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (log) { + if (pr_version > 1) + LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version); + } + + // Skip pr_psinfosz, pr_fname, pr_psargs + offset += 108; + if (lp64) + offset += 4; + + process.SetID(data.GetU32(&offset)); // pr_pid +} + static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data, uint32_t &cpi_nlwps, uint32_t &cpi_signo, @@ -522,6 +529,11 @@ ProcessElfCore::parseSegment(const DataExtractor &segment) { } llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { + ArchSpec arch = GetArchitecture(); + bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || + arch.GetMachine() == llvm::Triple::mips64 || + arch.GetMachine() == llvm::Triple::ppc64 || + arch.GetMachine() == llvm::Triple::x86_64); bool have_prstatus = false; bool have_prpsinfo = false; ThreadData thread_data; @@ -542,10 +554,11 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) { switch (note.info.n_type) { case ELF::NT_PRSTATUS: have_prstatus = true; - ParseFreeBSDPrStatus(thread_data, note.data, GetArchitecture()); + ParseFreeBSDPrStatus(thread_data, note.data, lp64); break; case ELF::NT_PRPSINFO: have_prpsinfo = true; + ParseFreeBSDPrPsInfo(*this, note.data, lp64); break; case ELF::NT_FREEBSD_THRMISC: { lldb::offset_t offset = 0; @@ -651,6 +664,32 @@ llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) { thread_data.notes.push_back(note); } } break; + case llvm::Triple::x86: { + // Assume order PT_GETREGS, PT_GETFPREGS + if (note.info.n_type == NETBSD::I386::NT_REGS) { + // If this is the next thread, push the previous one first. + if (had_nt_regs) { + m_thread_data.push_back(thread_data); + thread_data = ThreadData(); + had_nt_regs = false; + } + + thread_data.gpregset = note.data; + thread_data.tid = tid; + if (thread_data.gpregset.GetByteSize() == 0) + return llvm::make_error<llvm::StringError>( + "Could not find general purpose registers note in core file.", + llvm::inconvertibleErrorCode()); + had_nt_regs = true; + } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) { + if (!had_nt_regs || tid != thread_data.tid) + return llvm::make_error<llvm::StringError>( + "Error parsing NetBSD core(5) notes: Unexpected order " + "of NOTEs PT_GETFPREG before PT_GETREG", + llvm::inconvertibleErrorCode()); + thread_data.notes.push_back(note); + } + } break; case llvm::Triple::x86_64: { // Assume order PT_GETREGS, PT_GETFPREGS if (note.info.n_type == NETBSD::AMD64::NT_REGS) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp index 2f71f175a00d..f0aee04b5f62 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -25,7 +25,7 @@ RegisterContextCorePOSIX_arm::RegisterContextCorePOSIX_arm( m_gpr.SetByteOrder(gpregset.GetByteOrder()); } -RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() {} +RegisterContextCorePOSIX_arm::~RegisterContextCorePOSIX_arm() = default; bool RegisterContextCorePOSIX_arm::ReadGPR() { return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 129a887a550c..e56aa88b57d9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -17,26 +17,52 @@ using namespace lldb_private; +std::unique_ptr<RegisterContextCorePOSIX_arm64> +RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch, + const DataExtractor &gpregset, + llvm::ArrayRef<CoreNote> notes) { + Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskDefault; + + DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc); + if (sve_data.GetByteSize() > sizeof(sve::user_sve_header)) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); + + // Pointer Authentication register set data is based on struct + // user_pac_mask declared in ptrace.h. See reference implementation + // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h. + DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc); + if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth); + + auto register_info_up = + std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets); + return std::unique_ptr<RegisterContextCorePOSIX_arm64>( + new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up), + gpregset, notes)); +} + RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64( Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes) : RegisterContextPOSIX_arm64(thread, std::move(register_info)) { - m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(), - gpregset.GetByteSize()); - m_gpr.SetData(m_gpr_buffer); - m_gpr.SetByteOrder(gpregset.GetByteOrder()); + m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(), + gpregset.GetByteSize())); + m_gpr_data.SetByteOrder(gpregset.GetByteOrder()); - m_fpregset = getRegset( - notes, m_register_info_up->GetTargetArchitecture().GetTriple(), FPR_Desc); + const llvm::Triple &target_triple = + m_register_info_up->GetTargetArchitecture().GetTriple(); + m_fpr_data = getRegset(notes, target_triple, FPR_Desc); - m_sveregset = - getRegset(notes, m_register_info_up->GetTargetArchitecture().GetTriple(), - AARCH64_SVE_Desc); + if (m_register_info_up->IsSVEEnabled()) + m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc); + + if (m_register_info_up->IsPAuthEnabled()) + m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc); ConfigureRegisterContext(); } -RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {} +RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() = default; bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; } @@ -53,16 +79,16 @@ bool RegisterContextCorePOSIX_arm64::WriteFPR() { } const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) { - return m_sveregset.GetDataStart() + offset; + return m_sve_data.GetDataStart() + offset; } void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() { - if (m_sveregset.GetByteSize() > sizeof(sve::user_sve_header)) { + if (m_sve_data.GetByteSize() > sizeof(sve::user_sve_header)) { uint64_t sve_header_field_offset = 8; - m_sve_vector_length = m_sveregset.GetU16(&sve_header_field_offset); + m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset); sve_header_field_offset = 12; uint16_t sve_header_flags_field = - m_sveregset.GetU16(&sve_header_field_offset); + m_sve_data.GetU16(&sve_header_field_offset); if ((sve_header_flags_field & sve::ptrace_regs_mask) == sve::ptrace_regs_fpsimd) m_sve_state = SVEState::FPSIMD; @@ -70,15 +96,16 @@ void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() { sve::ptrace_regs_sve) m_sve_state = SVEState::Full; - if (sve::vl_valid(m_sve_vector_length)) - m_register_info_up->ConfigureVectorRegisterInfos( - sve::vq_from_vl(m_sve_vector_length)); - else { + if (!sve::vl_valid(m_sve_vector_length)) { m_sve_state = SVEState::Disabled; m_sve_vector_length = 0; } } else m_sve_state = SVEState::Disabled; + + if (m_sve_state != SVEState::Disabled) + m_register_info_up->ConfigureVectorLength( + sve::vq_from_vl(m_sve_vector_length)); } uint32_t RegisterContextCorePOSIX_arm64::CalculateSVEOffset( @@ -104,7 +131,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, offset = reg_info->byte_offset; if (offset + reg_info->byte_size <= GetGPRSize()) { - uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) { value = v; return true; @@ -119,8 +146,8 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, if (m_sve_state == SVEState::Disabled) { // SVE is disabled take legacy route for FPU register access offset -= GetGPRSize(); - if (offset < m_fpregset.GetByteSize()) { - value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset, + if (offset < m_fpr_data.GetByteSize()) { + value.SetFromMemoryData(reg_info, m_fpr_data.GetDataStart() + offset, reg_info->byte_size, lldb::eByteOrderLittle, error); return error.Success(); @@ -152,7 +179,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, } assert(sve_reg_num != LLDB_INVALID_REGNUM); - assert(offset < m_sveregset.GetByteSize()); + assert(offset < m_sve_data.GetByteSize()); value.SetFromMemoryData(reg_info, GetSVEBuffer(offset), reg_info->byte_size, lldb::eByteOrderLittle, error); @@ -174,7 +201,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, if (IsSVEZ(reg)) { byte_size = 16; offset = CalculateSVEOffset(reg_info); - assert(offset < m_sveregset.GetByteSize()); + assert(offset < m_sve_data.GetByteSize()); src = GetSVEBuffer(offset); } value.SetFromMemoryData(reg_info, src, byte_size, lldb::eByteOrderLittle, @@ -182,7 +209,7 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, } break; case SVEState::Full: offset = CalculateSVEOffset(reg_info); - assert(offset < m_sveregset.GetByteSize()); + assert(offset < m_sve_data.GetByteSize()); value.SetFromMemoryData(reg_info, GetSVEBuffer(offset), reg_info->byte_size, lldb::eByteOrderLittle, error); @@ -191,6 +218,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, default: return false; } + } else if (IsPAuth(reg)) { + offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset(); + assert(offset < m_pac_data.GetByteSize()); + value.SetFromMemoryData(reg_info, m_pac_data.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, error); } else return false; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index a4fdc4f14328..3988e3539b89 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -18,11 +18,10 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { public: - RegisterContextCorePOSIX_arm64( - lldb_private::Thread &thread, - std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, - const lldb_private::DataExtractor &gpregset, - llvm::ArrayRef<lldb_private::CoreNote> notes); + static std::unique_ptr<RegisterContextCorePOSIX_arm64> + Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch, + const lldb_private::DataExtractor &gpregset, + llvm::ArrayRef<lldb_private::CoreNote> notes); ~RegisterContextCorePOSIX_arm64() override; @@ -39,6 +38,12 @@ public: bool HardwareSingleStep(bool enable) override; protected: + RegisterContextCorePOSIX_arm64( + lldb_private::Thread &thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info, + const lldb_private::DataExtractor &gpregset, + llvm::ArrayRef<lldb_private::CoreNote> notes); + bool ReadGPR() override; bool ReadFPR() override; @@ -48,10 +53,10 @@ protected: bool WriteFPR() override; private: - lldb::DataBufferSP m_gpr_buffer; - lldb_private::DataExtractor m_gpr; - lldb_private::DataExtractor m_fpregset; - lldb_private::DataExtractor m_sveregset; + lldb_private::DataExtractor m_gpr_data; + lldb_private::DataExtractor m_fpr_data; + lldb_private::DataExtractor m_sve_data; + lldb_private::DataExtractor m_pac_data; SVEState m_sve_state; uint16_t m_sve_vector_length = 0; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index b5b83d899a44..5b1eb8b5437d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -32,7 +32,7 @@ RegisterContextCorePOSIX_mips64::RegisterContextCorePOSIX_mips64( m_fpr.SetByteOrder(fpregset.GetByteOrder()); } -RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() {} +RegisterContextCorePOSIX_mips64::~RegisterContextCorePOSIX_mips64() = default; bool RegisterContextCorePOSIX_mips64::ReadGPR() { return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index e15cd47cd7da..8380731692a3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -39,7 +39,7 @@ RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc( m_vec.SetByteOrder(vregset.GetByteOrder()); } -RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() {} +RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc() = default; bool RegisterContextCorePOSIX_powerpc::ReadGPR() { return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp index c3aa92c9f86c..f1cd6897616d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -33,7 +33,7 @@ RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x( m_fpr.SetByteOrder(fpregset.GetByteOrder()); } -RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() {} +RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() = default; bool RegisterContextCorePOSIX_s390x::ReadGPR() { return true; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h index 25abd7ed54b7..f6a2fbdcc938 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -55,6 +55,10 @@ namespace AMD64 { enum { NT_REGS = 33, NT_FPREGS = 35 }; } +namespace I386 { +enum { NT_REGS = 33, NT_FPREGS = 35 }; +} + } // namespace NETBSD namespace OPENBSD { @@ -96,6 +100,9 @@ DataExtractor getRegset(llvm::ArrayRef<CoreNote> Notes, llvm::ArrayRef<RegsetDesc> RegsetDescs); constexpr RegsetDesc FPR_Desc[] = { + // FreeBSD/i386 core NT_FPREGSET is x87 FSAVE result but the XSAVE dump + // starts with FXSAVE struct, so use that instead if available. + {llvm::Triple::FreeBSD, llvm::Triple::x86, llvm::ELF::NT_X86_XSTATE}, {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::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. @@ -103,6 +110,7 @@ constexpr RegsetDesc FPR_Desc[] = { {llvm::Triple::Linux, llvm::Triple::x86, llvm::ELF::NT_PRXFPREG}, {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_FPREGSET}, {llvm::Triple::NetBSD, llvm::Triple::aarch64, NETBSD::AARCH64::NT_FPREGS}, + {llvm::Triple::NetBSD, llvm::Triple::x86, NETBSD::I386::NT_FPREGS}, {llvm::Triple::NetBSD, llvm::Triple::x86_64, NETBSD::AMD64::NT_FPREGS}, {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, }; @@ -111,6 +119,10 @@ constexpr RegsetDesc AARCH64_SVE_Desc[] = { {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE}, }; +constexpr RegsetDesc AARCH64_PAC_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK}, +}; + constexpr RegsetDesc PPC_VMX_Desc[] = { {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 6c3ee9debc7c..5086cfaa6536 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -18,12 +18,11 @@ #include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterContextLinux_i386.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips.h" -#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" #ifdef LLDB_ENABLE_ALL #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #endif // LLDB_ENABLE_ALL #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" +#include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h" #include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h" #include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h" @@ -113,6 +112,9 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: break; + case llvm::Triple::x86: + reg_interface = new RegisterContextNetBSD_i386(arch); + break; case llvm::Triple::x86_64: reg_interface = new RegisterContextNetBSD_x86_64(arch); break; @@ -126,14 +128,6 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: break; - case llvm::Triple::mipsel: - case llvm::Triple::mips: - reg_interface = new RegisterContextLinux_mips(arch); - break; - case llvm::Triple::mips64el: - case llvm::Triple::mips64: - reg_interface = new RegisterContextLinux_mips64(arch); - break; case llvm::Triple::ppc64le: reg_interface = new RegisterInfoPOSIX_ppc64le(arch); break; @@ -183,9 +177,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: - m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm64>( - *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch), - m_gpregset_data, m_notes); + m_thread_reg_ctx_sp = RegisterContextCorePOSIX_arm64::Create( + *this, arch, m_gpregset_data, m_notes); break; case llvm::Triple::arm: m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_arm>( diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp index fdaa60e2df41..a4c71e864a76 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp @@ -20,7 +20,10 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; using namespace std::chrono; -static const seconds kInterruptTimeout(5); +// When we've sent a continue packet and are waiting for the target to stop, +// we wake up the wait with this interval to make sure the stub hasn't gone +// away while we were waiting. +static const seconds kWakeupInterval(5); ///////////////////////// // GDBRemoteClientBase // @@ -35,7 +38,8 @@ GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name, StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response) { + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); response.Clear(); @@ -48,16 +52,37 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( if (!cont_lock) return eStateInvalid; OnRunPacketSent(true); - + // The main ReadPacket loop wakes up at computed_timeout intervals, just to + // check that the connection hasn't dropped. When we wake up we also check + // whether there is an interrupt request that has reached its endpoint. + // If we want a shorter interrupt timeout that kWakeupInterval, we need to + // choose the shorter interval for the wake up as well. + std::chrono::seconds computed_timeout = std::min(interrupt_timeout, + kWakeupInterval); for (;;) { - PacketResult read_result = ReadPacket(response, kInterruptTimeout, false); + PacketResult read_result = ReadPacket(response, computed_timeout, false); + // Reset the computed_timeout to the default value in case we are going + // round again. + computed_timeout = std::min(interrupt_timeout, kWakeupInterval); switch (read_result) { case PacketResult::ErrorReplyTimeout: { std::lock_guard<std::mutex> lock(m_mutex); - if (m_async_count == 0) + if (m_async_count == 0) { continue; - if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout) + } + auto cur_time = steady_clock::now(); + if (cur_time >= m_interrupt_endpoint) return eStateInvalid; + else { + // We woke up and found an interrupt is in flight, but we haven't + // exceeded the interrupt wait time. So reset the wait time to the + // time left till the interrupt timeout. But don't wait longer + // than our wakeup timeout. + auto new_wait = m_interrupt_endpoint - cur_time; + computed_timeout = std::min(kWakeupInterval, + std::chrono::duration_cast<std::chrono::seconds>(new_wait)); + continue; + } break; } case PacketResult::Success: @@ -133,8 +158,9 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse( } } -bool GDBRemoteClientBase::SendAsyncSignal(int signo) { - Lock lock(*this, true); +bool GDBRemoteClientBase::SendAsyncSignal( + int signo, std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock || !lock.DidInterrupt()) return false; @@ -144,25 +170,26 @@ bool GDBRemoteClientBase::SendAsyncSignal(int signo) { return true; } -bool GDBRemoteClientBase::Interrupt() { - Lock lock(*this, true); +bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock.DidInterrupt()) return false; m_should_stop = true; return true; } + GDBRemoteCommunication::PacketResult GDBRemoteClientBase::SendPacketAndWaitForResponse( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async) { - Lock lock(*this, send_async); + std::chrono::seconds interrupt_timeout) { + Lock lock(*this, interrupt_timeout); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) LLDB_LOGF(log, "GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), send_async); + "packet '%.*s'", + __FUNCTION__, int(payload.size()), payload.data()); return PacketResult::ErrorSendFailed; } @@ -172,16 +199,16 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse( GDBRemoteCommunication::PacketResult GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async, + std::chrono::seconds interrupt_timeout, llvm::function_ref<void(llvm::StringRef)> output_callback) { - Lock lock(*this, send_async); + Lock lock(*this, interrupt_timeout); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)) LLDB_LOGF(log, "GDBRemoteClientBase::%s failed to get mutex, not sending " - "packet '%.*s' (send_async=%d)", - __FUNCTION__, int(payload.size()), payload.data(), send_async); + "packet '%.*s'", + __FUNCTION__, int(payload.size()), payload.data()); return PacketResult::ErrorSendFailed; } @@ -222,13 +249,14 @@ GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock( return packet_result; } -bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, - StringExtractorGDBRemote &response) { +bool GDBRemoteClientBase::SendvContPacket( + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__); // we want to lock down packet sending while we continue - Lock lock(*this, true); + Lock lock(*this, interrupt_timeout); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", @@ -336,18 +364,20 @@ GDBRemoteClientBase::ContinueLock::lock() { // GDBRemoteClientBase::Lock // /////////////////////////////// -GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt) +GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, + std::chrono::seconds interrupt_timeout) : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm), - m_acquired(false), m_did_interrupt(false) { - SyncWithContinueThread(interrupt); + m_interrupt_timeout(interrupt_timeout), m_acquired(false), + m_did_interrupt(false) { + SyncWithContinueThread(); if (m_acquired) m_async_lock.lock(); } -void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { +void GDBRemoteClientBase::Lock::SyncWithContinueThread() { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); std::unique_lock<std::mutex> lock(m_comm.m_mutex); - if (m_comm.m_is_running && !interrupt) + if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0)) return; // We were asked to avoid interrupting the sender. Lock is not // acquired. @@ -365,9 +395,9 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) { "interrupt packet"); return; } + m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout; if (log) log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03"); - m_comm.m_interrupt_time = steady_clock::now(); } m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; }); m_did_interrupt = true; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h index cd9f6ebd7642..518b81318b6c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h @@ -33,29 +33,46 @@ public: GDBRemoteClientBase(const char *comm_name, const char *listener_name); - bool SendAsyncSignal(int signo); + bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout); - bool Interrupt(); + bool Interrupt(std::chrono::seconds interrupt_timeout); lldb::StateType SendContinuePacketAndWaitForResponse( ContinueDelegate &delegate, const UnixSignals &signals, - llvm::StringRef payload, StringExtractorGDBRemote &response); - - PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, - StringExtractorGDBRemote &response, - bool send_async); + llvm::StringRef payload, std::chrono::seconds interrupt_timeout, + StringExtractorGDBRemote &response); + + // If interrupt_timeout == 0 seconds, don't interrupt the target. + // Only send the packet if the target is stopped. + // If you want to use this mode, use the fact that the timeout is defaulted + // so it's clear from the call-site that you are using no-interrupt. + // If it is non-zero, interrupt the target if it is running, and + // send the packet. + // It the target doesn't respond within the given timeout, it returns + // ErrorReplyTimeout. + PacketResult SendPacketAndWaitForResponse( + llvm::StringRef payload, StringExtractorGDBRemote &response, + std::chrono::seconds interrupt_timeout = std::chrono::seconds(0)); PacketResult SendPacketAndReceiveResponseWithOutputSupport( llvm::StringRef payload, StringExtractorGDBRemote &response, - bool send_async, + std::chrono::seconds interrupt_timeout, llvm::function_ref<void(llvm::StringRef)> output_callback); bool SendvContPacket(llvm::StringRef payload, + std::chrono::seconds interrupt_timeout, StringExtractorGDBRemote &response); class Lock { public: - Lock(GDBRemoteClientBase &comm, bool interrupt); + // If interrupt_timeout == 0 seconds, only take the lock if the target is + // not running. If using this option, use the fact that the + // interrupt_timeout is defaulted so it will be obvious at the call site + // that you are choosing this mode. If it is non-zero, interrupt the target + // if it is running, waiting for the given timeout for the interrupt to + // succeed. + Lock(GDBRemoteClientBase &comm, + std::chrono::seconds interrupt_timeout = std::chrono::seconds(0)); ~Lock(); explicit operator bool() { return m_acquired; } @@ -67,10 +84,11 @@ public: private: std::unique_lock<std::recursive_mutex> m_async_lock; GDBRemoteClientBase &m_comm; + std::chrono::seconds m_interrupt_timeout; bool m_acquired; bool m_did_interrupt; - void SyncWithContinueThread(bool interrupt); + void SyncWithContinueThread(); }; protected: @@ -109,7 +127,7 @@ private: /// When was the interrupt packet sent. Used to make sure we time out if the /// stub does not respond to interrupt requests. - std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time; + std::chrono::time_point<std::chrono::steady_clock> m_interrupt_endpoint; /// Number of threads interested in sending. uint32_t m_async_count; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 4981345d6a18..013d407c0fc1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -8,9 +8,9 @@ #include "GDBRemoteCommunication.h" +#include <climits> +#include <cstring> #include <future> -#include <limits.h> -#include <string.h> #include <sys/stat.h> #include "lldb/Core/StreamFile.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index d375a312ae2c..b16aed4f5c90 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -8,7 +8,7 @@ #include "GDBRemoteCommunicationClient.h" -#include <math.h> +#include <cmath> #include <sys/stat.h> #include <numeric> @@ -16,6 +16,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" #include "lldb/Host/XML.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/MemoryRegionInfo.h" @@ -55,40 +56,7 @@ llvm::raw_ostream &process_gdb_remote::operator<<(llvm::raw_ostream &os, // GDBRemoteCommunicationClient constructor GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"), - m_supports_not_sending_acks(eLazyBoolCalculate), - m_supports_thread_suffix(eLazyBoolCalculate), - m_supports_threads_in_stop_reply(eLazyBoolCalculate), - m_supports_vCont_all(eLazyBoolCalculate), - m_supports_vCont_any(eLazyBoolCalculate), - m_supports_vCont_c(eLazyBoolCalculate), - m_supports_vCont_C(eLazyBoolCalculate), - m_supports_vCont_s(eLazyBoolCalculate), - m_supports_vCont_S(eLazyBoolCalculate), - m_qHostInfo_is_valid(eLazyBoolCalculate), - m_curr_pid_is_valid(eLazyBoolCalculate), - m_qProcessInfo_is_valid(eLazyBoolCalculate), - m_qGDBServerVersion_is_valid(eLazyBoolCalculate), - m_supports_alloc_dealloc_memory(eLazyBoolCalculate), - m_supports_memory_region_info(eLazyBoolCalculate), - m_supports_watchpoint_support_info(eLazyBoolCalculate), - m_supports_detach_stay_stopped(eLazyBoolCalculate), - m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), - m_attach_or_wait_reply(eLazyBoolCalculate), - m_prepare_for_reg_writing_reply(eLazyBoolCalculate), - m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate), - m_avoid_g_packets(eLazyBoolCalculate), - m_supports_QSaveRegisterState(eLazyBoolCalculate), - m_supports_qXfer_auxv_read(eLazyBoolCalculate), - m_supports_qXfer_libraries_read(eLazyBoolCalculate), - m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate), - m_supports_qXfer_features_read(eLazyBoolCalculate), - m_supports_qXfer_memory_map_read(eLazyBoolCalculate), - m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate), - m_supports_jThreadExtendedInfo(eLazyBoolCalculate), - m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), - m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), - m_supports_QPassSignals(eLazyBoolCalculate), - m_supports_error_string_reply(eLazyBoolCalculate), + m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -97,15 +65,11 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true), m_qSymbol_requests_done(false), m_supports_qModuleInfo(true), m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true), - m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID), - m_curr_tid_run(LLDB_INVALID_THREAD_ID), - m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(), - m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(), - m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0), - m_max_packet_size(0), m_qSupported_response(), - m_supported_async_json_packets_is_valid(false), - m_supported_async_json_packets_sp(), m_qXfer_memory_map(), - m_qXfer_memory_map_loaded(false) {} + + m_host_arch(), m_process_arch(), m_os_build(), m_os_kernel(), + m_hostname(), m_gdb_server_name(), m_default_packet_timeout(0), + m_qSupported_response(), m_supported_async_json_packets_sp(), + m_qXfer_memory_map() {} // Destructor GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() { @@ -218,7 +182,7 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() { ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6))); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == + if (SendPacketAndWaitForResponse("QStartNoAckMode", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_send_acks = false; @@ -235,8 +199,8 @@ void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() { m_supports_threads_in_stop_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_supports_threads_in_stop_reply = eLazyBoolYes; } @@ -248,8 +212,8 @@ bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() { m_attach_or_wait_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_attach_or_wait_reply = eLazyBoolYes; } @@ -262,8 +226,8 @@ bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() { m_prepare_for_reg_writing_reply = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_prepare_for_reg_writing_reply = eLazyBoolYes; } @@ -292,6 +256,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { m_prepare_for_reg_writing_reply = eLazyBoolCalculate; m_attach_or_wait_reply = eLazyBoolCalculate; m_avoid_g_packets = eLazyBoolCalculate; + m_supports_multiprocess = eLazyBoolCalculate; m_supports_qXfer_auxv_read = eLazyBoolCalculate; m_supports_qXfer_libraries_read = eLazyBoolCalculate; m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; @@ -321,6 +286,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) { m_gdb_server_name.clear(); m_gdb_server_version = UINT32_MAX; m_default_packet_timeout = seconds(0); + m_target_vm_page_size = 0; m_max_packet_size = 0; m_qSupported_response.clear(); m_supported_async_json_packets_is_valid = false; @@ -342,11 +308,17 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { m_supports_augmented_libraries_svr4_read = eLazyBoolNo; m_supports_qXfer_features_read = eLazyBoolNo; m_supports_qXfer_memory_map_read = eLazyBoolNo; + m_supports_multiprocess = eLazyBoolNo; + m_supports_qEcho = eLazyBoolNo; + m_supports_QPassSignals = eLazyBoolNo; + m_supports_memory_tagging = eLazyBoolNo; + m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if // not, we assume no limit // build the qSupported packet - std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc"}; + std::vector<std::string> features = {"xmlRegisters=i386,arm,mips,arc", + "multiprocess+"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { @@ -355,97 +327,57 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() { } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, - /*send_async=*/false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { - const char *response_cstr = response.GetStringRef().data(); - // Hang on to the qSupported packet, so that platforms can do custom // configuration of the transport before attaching/launching the process. - m_qSupported_response = response_cstr; - - if (::strstr(response_cstr, "qXfer:auxv:read+")) - m_supports_qXfer_auxv_read = eLazyBoolYes; - if (::strstr(response_cstr, "qXfer:libraries-svr4:read+")) - m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; - if (::strstr(response_cstr, "augmented-libraries-svr4-read")) { - m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied - m_supports_augmented_libraries_svr4_read = eLazyBoolYes; - } - if (::strstr(response_cstr, "qXfer:libraries:read+")) - m_supports_qXfer_libraries_read = eLazyBoolYes; - if (::strstr(response_cstr, "qXfer:features:read+")) - m_supports_qXfer_features_read = eLazyBoolYes; - if (::strstr(response_cstr, "qXfer:memory-map:read+")) - m_supports_qXfer_memory_map_read = eLazyBoolYes; - - // Look for a list of compressions in the features list e.g. - // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib- - // deflate,lzma - const char *features_list = ::strstr(response_cstr, "qXfer:features:"); - if (features_list) { - const char *compressions = - ::strstr(features_list, "SupportedCompressions="); - if (compressions) { - std::vector<std::string> supported_compressions; - compressions += sizeof("SupportedCompressions=") - 1; - const char *end_of_compressions = strchr(compressions, ';'); - if (end_of_compressions == nullptr) { - end_of_compressions = strchr(compressions, '\0'); - } - const char *current_compression = compressions; - while (current_compression < end_of_compressions) { - const char *next_compression_name = strchr(current_compression, ','); - const char *end_of_this_word = next_compression_name; - if (next_compression_name == nullptr || - end_of_compressions < next_compression_name) { - end_of_this_word = end_of_compressions; - } - - if (end_of_this_word) { - if (end_of_this_word == current_compression) { - current_compression++; - } else { - std::string this_compression( - current_compression, end_of_this_word - current_compression); - supported_compressions.push_back(this_compression); - current_compression = end_of_this_word + 1; - } - } else { - supported_compressions.push_back(current_compression); - current_compression = end_of_compressions; - } - } - - if (supported_compressions.size() > 0) { - MaybeEnableCompression(supported_compressions); + m_qSupported_response = response.GetStringRef().str(); + + llvm::SmallVector<llvm::StringRef, 16> server_features; + response.GetStringRef().split(server_features, ';'); + + for (llvm::StringRef x : server_features) { + if (x == "qXfer:auxv:read+") + m_supports_qXfer_auxv_read = eLazyBoolYes; + else if (x == "qXfer:libraries-svr4:read+") + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; + else if (x == "augmented-libraries-svr4-read") { + m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied + m_supports_augmented_libraries_svr4_read = eLazyBoolYes; + } else if (x == "qXfer:libraries:read+") + m_supports_qXfer_libraries_read = eLazyBoolYes; + else if (x == "qXfer:features:read+") + m_supports_qXfer_features_read = eLazyBoolYes; + else if (x == "qXfer:memory-map:read+") + m_supports_qXfer_memory_map_read = eLazyBoolYes; + else if (x == "qEcho") + m_supports_qEcho = eLazyBoolYes; + else if (x == "QPassSignals+") + m_supports_QPassSignals = eLazyBoolYes; + else if (x == "multiprocess+") + m_supports_multiprocess = eLazyBoolYes; + else if (x == "memory-tagging+") + m_supports_memory_tagging = eLazyBoolYes; + // Look for a list of compressions in the features list e.g. + // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib- + // deflate,lzma + else if (x.consume_front("SupportedCompressions=")) { + llvm::SmallVector<llvm::StringRef, 4> compressions; + x.split(compressions, ','); + if (!compressions.empty()) + MaybeEnableCompression(compressions); + } else if (x.consume_front("PacketSize=")) { + StringExtractorGDBRemote packet_response(x); + m_max_packet_size = + packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); + if (m_max_packet_size == 0) { + m_max_packet_size = UINT64_MAX; // Must have been a garbled response + Log *log( + ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response"); } } } - - if (::strstr(response_cstr, "qEcho")) - m_supports_qEcho = eLazyBoolYes; - else - m_supports_qEcho = eLazyBoolNo; - - if (::strstr(response_cstr, "QPassSignals+")) - m_supports_QPassSignals = eLazyBoolYes; - else - m_supports_QPassSignals = eLazyBoolNo; - - const char *packet_size_str = ::strstr(response_cstr, "PacketSize="); - if (packet_size_str) { - StringExtractorGDBRemote packet_response(packet_size_str + - strlen("PacketSize=")); - m_max_packet_size = - packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX); - if (m_max_packet_size == 0) { - m_max_packet_size = UINT64_MAX; // Must have been a garbled response - Log *log( - ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response"); - } - } } } @@ -453,8 +385,8 @@ bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() { if (m_supports_thread_suffix == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_thread_suffix = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response) == + PacketResult::Success) { if (response.IsOKResponse()) m_supports_thread_suffix = eLazyBoolYes; } @@ -470,7 +402,7 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { m_supports_vCont_C = eLazyBoolNo; m_supports_vCont_s = eLazyBoolNo; m_supports_vCont_S = eLazyBoolNo; - if (SendPacketAndWaitForResponse("vCont?", response, false) == + if (SendPacketAndWaitForResponse("vCont?", response) == PacketResult::Success) { const char *response_cstr = response.GetStringRef().data(); if (::strstr(response_cstr, ";c")) @@ -522,9 +454,9 @@ bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse( - lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response, - bool send_async) { - Lock lock(*this, send_async); + lldb::tid_t tid, StreamString &&payload, + StringExtractorGDBRemote &response) { + Lock lock(*this); if (!lock) { if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet( GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) @@ -561,7 +493,7 @@ LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported( payload.PutCString(packetStr); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) == PacketResult::Success && + tid, std::move(payload), response) == PacketResult::Success && response.IsNormalResponse()) { return eLazyBoolYes; } @@ -575,7 +507,7 @@ StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() { if (m_supports_jThreadsInfo) { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == + if (SendPacketAndWaitForResponse("jThreadsInfo", response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) { m_supports_jThreadsInfo = false; @@ -592,7 +524,7 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() { if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jThreadExtendedInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == + if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jThreadExtendedInfo = eLazyBoolYes; @@ -608,7 +540,7 @@ void GDBRemoteCommunicationClient::EnableErrorStringInPacket() { // We try to enable error strings in remote packets but if we fail, we just // work in the older way. m_supports_error_string_reply = eLazyBoolNo; - if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) == + if (SendPacketAndWaitForResponse("QEnableErrorStrings", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_error_string_reply = eLazyBoolYes; @@ -622,8 +554,7 @@ bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { StringExtractorGDBRemote response; m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", - response, - false) == PacketResult::Success) { + response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; } @@ -636,7 +567,7 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jGetSharedCacheInfo = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == + if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response) == PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jGetSharedCacheInfo = eLazyBoolYes; @@ -646,13 +577,82 @@ bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() { return m_supports_jGetSharedCacheInfo; } +bool GDBRemoteCommunicationClient::GetMemoryTaggingSupported() { + if (m_supports_memory_tagging == eLazyBoolCalculate) { + GetRemoteQSupported(); + } + return m_supports_memory_tagging == eLazyBoolYes; +} + +DataBufferSP GDBRemoteCommunicationClient::ReadMemoryTags(lldb::addr_t addr, + size_t len, + int32_t type) { + StreamString packet; + packet.Printf("qMemTags:%" PRIx64 ",%zx:%" PRIx32, addr, len, type); + StringExtractorGDBRemote response; + + Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_MEMORY); + + if (SendPacketAndWaitForResponse(packet.GetString(), response) != + PacketResult::Success || + !response.IsNormalResponse()) { + LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s: qMemTags packet failed", + __FUNCTION__); + return nullptr; + } + + // We are expecting + // m<hex encoded bytes> + + if (response.GetChar() != 'm') { + LLDB_LOGF(log, + "GDBRemoteCommunicationClient::%s: qMemTags response did not " + "begin with \"m\"", + __FUNCTION__); + return nullptr; + } + + size_t expected_bytes = response.GetBytesLeft() / 2; + DataBufferSP buffer_sp(new DataBufferHeap(expected_bytes, 0)); + size_t got_bytes = response.GetHexBytesAvail(buffer_sp->GetData()); + // Check both because in some situations chars are consumed even + // if the decoding fails. + if (response.GetBytesLeft() || (expected_bytes != got_bytes)) { + LLDB_LOGF( + log, + "GDBRemoteCommunicationClient::%s: Invalid data in qMemTags response", + __FUNCTION__); + return nullptr; + } + + return buffer_sp; +} + +Status GDBRemoteCommunicationClient::WriteMemoryTags( + lldb::addr_t addr, size_t len, int32_t type, + const std::vector<uint8_t> &tags) { + // Format QMemTags:address,length:type:tags + StreamString packet; + packet.Printf("QMemTags:%" PRIx64 ",%zx:%" PRIx32 ":", addr, len, type); + packet.PutBytesAsRawHex8(tags.data(), tags.size()); + + Status status; + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(packet.GetString(), response) != + PacketResult::Success || + !response.IsOKResponse()) { + status.SetErrorString("QMemTags packet failed"); + } + return status; +} + bool GDBRemoteCommunicationClient::GetxPacketSupported() { if (m_supports_x == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_x = eLazyBoolNo; char packet[256]; snprintf(packet, sizeof(packet), "x0,0"); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) m_supports_x = eLazyBoolYes; @@ -664,7 +664,7 @@ bool GDBRemoteCommunicationClient::GetxPacketSupported() { GDBRemoteCommunicationClient::PacketResult GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses( const char *payload_prefix, std::string &response_string) { - Lock lock(*this, false); + Lock lock(*this); if (!lock) { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); @@ -725,11 +725,11 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { // the thread id, which newer debugserver and lldb-gdbserver stubs return // correctly. StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse("qC", response) == PacketResult::Success) { if (response.GetChar() == 'Q') { if (response.GetChar() == 'C') { - m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID); + m_curr_pid_run = m_curr_pid = + response.GetHexMaxU64(false, LLDB_INVALID_PROCESS_ID); if (m_curr_pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; @@ -741,12 +741,14 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { // If we don't get a response for $qC, check if $qfThreadID gives us a // result. if (m_curr_pid == LLDB_INVALID_PROCESS_ID) { - std::vector<lldb::tid_t> thread_ids; bool sequence_mutex_unavailable; - size_t size; - size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable); - if (size && !sequence_mutex_unavailable) { - m_curr_pid = thread_ids.front(); + auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable); + if (!ids.empty() && !sequence_mutex_unavailable) { + // If server returned an explicit PID, use that. + m_curr_pid_run = m_curr_pid = ids.front().first; + // Otherwise, use the TID of the first thread (Linux hack). + if (m_curr_pid == LLDB_INVALID_PROCESS_ID) + m_curr_pid_run = m_curr_pid = ids.front().second; m_curr_pid_is_valid = eLazyBoolYes; return m_curr_pid; } @@ -759,7 +761,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) { bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) { error_str.clear(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) == + if (SendPacketAndWaitForResponse("qLaunchSuccess", response) == PacketResult::Success) { if (response.IsOKResponse()) return true; @@ -813,7 +815,7 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket( } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -863,7 +865,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket( if (m_supports_QEnvironmentHexEncoded) { packet.PutCString("QEnvironmentHexEncoded:"); packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value)); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -877,7 +879,7 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket( } else if (m_supports_QEnvironment) { packet.Printf("QEnvironment:%s", name_equal_value); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -897,7 +899,7 @@ int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) { StreamString packet; packet.Printf("QLaunchArch:%s", arch); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -915,7 +917,7 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket( StreamString packet; packet.Printf("QSetProcessEvent:%s", data); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) { if (was_supported) @@ -1000,7 +1002,7 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() { m_qGDBServerVersion_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) == + if (SendPacketAndWaitForResponse("qGDBServerVersion", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name, value; @@ -1025,9 +1027,9 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() { } void GDBRemoteCommunicationClient::MaybeEnableCompression( - std::vector<std::string> supported_compressions) { + llvm::ArrayRef<llvm::StringRef> supported_compressions) { CompressionType avail_type = CompressionType::None; - std::string avail_name; + llvm::StringRef avail_name; #if defined(HAVE_LIBCOMPRESSION) if (avail_type == CompressionType::None) { @@ -1091,8 +1093,8 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression( if (avail_type != CompressionType::None) { StringExtractorGDBRemote response; - std::string packet = "QEnableCompression:type:" + avail_name + ";"; - if (SendPacketAndWaitForResponse(packet, response, false) != + llvm::Twine packet = "QEnableCompression:type:" + avail_name + ";"; + if (SendPacketAndWaitForResponse(packet.str(), response) != PacketResult::Success) return; @@ -1118,15 +1120,29 @@ uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() { bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qC", response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse("qC", response) != PacketResult::Success) return false; if (!response.IsNormalResponse()) return false; - if (response.GetChar() == 'Q' && response.GetChar() == 'C') - tid = response.GetHexMaxU32(true, -1); + if (response.GetChar() == 'Q' && response.GetChar() == 'C') { + auto pid_tid = response.GetPidTid(0); + if (!pid_tid) + return false; + + lldb::pid_t pid = pid_tid->first; + // invalid + if (pid == StringExtractorGDBRemote::AllProcesses) + return false; + + // if we get pid as well, update m_curr_pid + if (pid != 0) { + m_curr_pid_run = m_curr_pid = pid; + m_curr_pid_is_valid = eLazyBoolYes; + } + tid = pid_tid->second; + } return true; } @@ -1154,7 +1170,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { ScopedTimeout timeout(*this, seconds(10)); m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qHostInfo", response, false) == + if (SendPacketAndWaitForResponse("qHostInfo", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; @@ -1219,11 +1235,13 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { } else if (name.equals("ptrsize")) { if (!value.getAsInteger(0, pointer_byte_size)) ++num_keys_decoded; + } else if (name.equals("addressing_bits")) { + if (!value.getAsInteger(0, m_addressing_bits)) + ++num_keys_decoded; } else if (name.equals("os_version") || - name.equals( - "version")) // Older debugserver binaries used the - // "version" key instead of - // "os_version"... + name.equals("version")) // Older debugserver binaries used + // the "version" key instead of + // "os_version"... { if (!m_os_version.tryParse(value)) ++num_keys_decoded; @@ -1245,6 +1263,12 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) { SetPacketTimeout(m_default_packet_timeout); ++num_keys_decoded; } + } else if (name.equals("vm-page-size")) { + int page_size; + if (!value.getAsInteger(0, page_size)) { + m_target_vm_page_size = page_size; + ++num_keys_decoded; + } } } @@ -1344,7 +1368,7 @@ int GDBRemoteCommunicationClient::SendAttach( ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid); UNUSED_IF_ASSERT_DISABLED(packet_len); assert(packet_len < (int)sizeof(packet)); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsErrorResponse()) return response.GetError(); @@ -1360,7 +1384,7 @@ int GDBRemoteCommunicationClient::SendStdinNotification(const char *data, packet.PutCString("I"); packet.PutBytesAsRawHex8(data, data_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { return 0; } @@ -1374,6 +1398,11 @@ GDBRemoteCommunicationClient::GetHostArchitecture() { return m_host_arch; } +uint32_t GDBRemoteCommunicationClient::GetAddressingBits() { + if (m_qHostInfo_is_valid == eLazyBoolCalculate) + GetHostInfo(); + return m_addressing_bits; +} seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() { if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo(); @@ -1393,7 +1422,7 @@ addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; @@ -1415,7 +1444,7 @@ bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_alloc_dealloc_memory = eLazyBoolNo; @@ -1439,7 +1468,7 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success && response.IsOKResponse()) { m_supports_detach_stay_stopped = eLazyBoolYes; @@ -1453,15 +1482,13 @@ Status GDBRemoteCommunicationClient::Detach(bool keep_stopped) { return error; } else { StringExtractorGDBRemote response; - PacketResult packet_result = - SendPacketAndWaitForResponse("D1", response, false); + PacketResult packet_result = SendPacketAndWaitForResponse("D1", response); if (packet_result != PacketResult::Success) error.SetErrorString("Sending extended disconnect packet failed."); } } else { StringExtractorGDBRemote response; - PacketResult packet_result = - SendPacketAndWaitForResponse("D", response, false); + PacketResult packet_result = SendPacketAndWaitForResponse("D", response); if (packet_result != PacketResult::Success) error.SetErrorString("Sending disconnect packet failed."); } @@ -1481,7 +1508,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success && response.GetResponseType() == StringExtractorGDBRemote::eResponse) { llvm::StringRef name; @@ -1551,9 +1578,30 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo( // Now convert the HEX bytes into a string value error_extractor.GetHexByteString(error_string); error.SetErrorString(error_string.c_str()); + } else if (name.equals("dirty-pages")) { + std::vector<addr_t> dirty_page_list; + std::string comma_sep_str = value.str(); + size_t comma_pos; + addr_t page; + while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) { + comma_sep_str[comma_pos] = '\0'; + page = StringConvert::ToUInt64(comma_sep_str.c_str(), + LLDB_INVALID_ADDRESS, 16); + if (page != LLDB_INVALID_ADDRESS) + dirty_page_list.push_back(page); + comma_sep_str.erase(0, comma_pos + 1); + } + page = StringConvert::ToUInt64(comma_sep_str.c_str(), + LLDB_INVALID_ADDRESS, 16); + if (page != LLDB_INVALID_ADDRESS) + dirty_page_list.push_back(page); + region_info.SetDirtyPageList(dirty_page_list); } } + if (m_target_vm_page_size != 0) + region_info.SetPageSize(m_target_vm_page_size); + if (region_info.GetRange().IsValid()) { // We got a valid address range back but no permissions -- which means // this is an unmapped page @@ -1718,8 +1766,8 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) { num = 0; if (m_supports_watchpoint_support_info != eLazyBoolNo) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) == + PacketResult::Success) { m_supports_watchpoint_support_info = eLazyBoolYes; llvm::StringRef name; llvm::StringRef value; @@ -1787,7 +1835,7 @@ int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1807,7 +1855,7 @@ int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1827,7 +1875,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1841,7 +1889,7 @@ int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) { bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) == + if (SendPacketAndWaitForResponse("qGetWorkingDir", response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) return false; @@ -1863,7 +1911,7 @@ int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) { packet.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; @@ -1882,8 +1930,7 @@ int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); @@ -1900,8 +1947,7 @@ int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsOKResponse()) return 0; uint8_t error = response.GetError(); @@ -2019,7 +2065,7 @@ bool GDBRemoteCommunicationClient::GetProcessInfo( assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { return DecodeProcessInfoResponse(response, process_info); } else { @@ -2044,7 +2090,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { GetHostInfo(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qProcessInfo", response, false) == + if (SendPacketAndWaitForResponse("qProcessInfo", response) == PacketResult::Success) { if (response.IsNormalResponse()) { llvm::StringRef name; @@ -2102,7 +2148,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { m_qProcessInfo_is_valid = eLazyBoolYes; if (pid != LLDB_INVALID_PROCESS_ID) { m_curr_pid_is_valid = eLazyBoolYes; - m_curr_pid = pid; + m_curr_pid_run = m_curr_pid = pid; } // Set the ArchSpec from the triple if we have it. @@ -2240,7 +2286,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( // Increase timeout as the first qfProcessInfo packet takes a long time on // Android. The value of 1min was arrived at empirically. ScopedTimeout timeout(*this, minutes(1)); - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) == + if (SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success) { do { ProcessInstanceInfo process_info; @@ -2248,7 +2294,7 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses( break; process_infos.push_back(process_info); response = StringExtractorGDBRemote(); - } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) == + } while (SendPacketAndWaitForResponse("qsProcessInfo", response) == PacketResult::Success); } else { m_supports_qfProcessInfo = false; @@ -2267,7 +2313,7 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is @@ -2294,7 +2340,7 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid, assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsNormalResponse()) { // Make sure we parsed the right number of characters. The response is @@ -2322,8 +2368,7 @@ bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) { StringExtractorGDBRemote response; // Send to target - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) if (response.IsOKResponse()) return true; @@ -2395,7 +2440,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, for (i = 0; i < num_packets; ++i) { const auto packet_start_time = steady_clock::now(); StringExtractorGDBRemote response; - SendPacketAndWaitForResponse(packet.GetString(), response, false); + SendPacketAndWaitForResponse(packet.GetString(), response); const auto packet_end_time = steady_clock::now(); packet_times.push_back(packet_end_time - packet_start_time); } @@ -2449,7 +2494,7 @@ void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets, uint32_t packet_count = 0; while (bytes_read < recv_amount) { StringExtractorGDBRemote response; - SendPacketAndWaitForResponse(packet.GetString(), response, false); + SendPacketAndWaitForResponse(packet.GetString(), response); bytes_read += recv_size; ++packet_count; } @@ -2503,7 +2548,7 @@ bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size, } StringExtractorGDBRemote response; - return SendPacketAndWaitForResponse(packet.GetString(), response, false) == + return SendPacketAndWaitForResponse(packet.GetString(), response) == PacketResult::Success; } @@ -2533,7 +2578,7 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer( // give the process a few seconds to startup ScopedTimeout timeout(*this, seconds(10)); - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { llvm::StringRef name; llvm::StringRef value; @@ -2557,7 +2602,7 @@ size_t GDBRemoteCommunicationClient::QueryGDBServer( connection_urls.clear(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != + if (SendPacketAndWaitForResponse("qQueryGDBServer", response) != PacketResult::Success) return 0; @@ -2596,7 +2641,7 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { stream.Printf("qKillSpawnedProcess:%" PRId64, pid); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.IsOKResponse()) return true; @@ -2604,25 +2649,27 @@ bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) { return false; } -bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) { - if (m_curr_tid == tid) - return true; +llvm::Optional<PidTid> +GDBRemoteCommunicationClient::SendSetCurrentThreadPacket(uint64_t tid, + uint64_t pid, + char op) { + lldb_private::StreamString packet; + packet.PutChar('H'); + packet.PutChar(op); + + if (pid != LLDB_INVALID_PROCESS_ID) + packet.Printf("p%" PRIx64 ".", pid); - char packet[32]; - int packet_len; if (tid == UINT64_MAX) - packet_len = ::snprintf(packet, sizeof(packet), "Hg-1"); + packet.PutCString("-1"); else - packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid); - assert(packet_len + 1 < (int)sizeof(packet)); - UNUSED_IF_ASSERT_DISABLED(packet_len); + packet.Printf("%" PRIx64, tid); + StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { - if (response.IsOKResponse()) { - m_curr_tid = tid; - return true; - } + if (SendPacketAndWaitForResponse(packet.GetString(), response) + == PacketResult::Success) { + if (response.IsOKResponse()) + return {{pid, tid}}; /* * Connected bare-iron target (like YAMON gdb-stub) may not have support for @@ -2630,55 +2677,46 @@ bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) { * The reply from '?' packet could be as simple as 'S05'. There is no packet * which can * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ - if (response.IsUnsupportedResponse() && IsConnected()) { - m_curr_tid = 1; - return true; - } + */ + if (response.IsUnsupportedResponse() && IsConnected()) + return {{1, 1}}; } - return false; + return llvm::None; } -bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) { - if (m_curr_tid_run == tid) +bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid, + uint64_t pid) { + if (m_curr_tid == tid && + (m_curr_pid == pid || LLDB_INVALID_PROCESS_ID == pid)) return true; - char packet[32]; - int packet_len; - if (tid == UINT64_MAX) - packet_len = ::snprintf(packet, sizeof(packet), "Hc-1"); - else - packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid); + llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'g'); + if (ret.hasValue()) { + if (ret->pid != LLDB_INVALID_PROCESS_ID) + m_curr_pid = ret->pid; + m_curr_tid = ret->tid; + } + return ret.hasValue(); +} - assert(packet_len + 1 < (int)sizeof(packet)); - UNUSED_IF_ASSERT_DISABLED(packet_len); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) == - PacketResult::Success) { - if (response.IsOKResponse()) { - m_curr_tid_run = tid; - return true; - } +bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid, + uint64_t pid) { + if (m_curr_tid_run == tid && + (m_curr_pid_run == pid || LLDB_INVALID_PROCESS_ID == pid)) + return true; - /* - * Connected bare-iron target (like YAMON gdb-stub) may not have support for - * Hc packet. - * The reply from '?' packet could be as simple as 'S05'. There is no packet - * which can - * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ - if (response.IsUnsupportedResponse() && IsConnected()) { - m_curr_tid_run = 1; - return true; - } + llvm::Optional<PidTid> ret = SendSetCurrentThreadPacket(tid, pid, 'c'); + if (ret.hasValue()) { + if (ret->pid != LLDB_INVALID_PROCESS_ID) + m_curr_pid_run = ret->pid; + m_curr_tid_run = ret->tid; } - return false; + return ret.hasValue(); } bool GDBRemoteCommunicationClient::GetStopReply( StringExtractorGDBRemote &response) { - if (SendPacketAndWaitForResponse("?", response, false) == - PacketResult::Success) + if (SendPacketAndWaitForResponse("?", response) == PacketResult::Success) return response.IsNormalResponse(); return false; } @@ -2691,7 +2729,7 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid); assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); - if (SendPacketAndWaitForResponse(packet, response, false) == + if (SendPacketAndWaitForResponse(packet, response) == PacketResult::Success) { if (response.IsUnsupportedResponse()) m_supports_qThreadStopInfo = false; @@ -2707,7 +2745,8 @@ bool GDBRemoteCommunicationClient::GetThreadStopInfo( } uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( - GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { + GDBStoppointType type, bool insert, addr_t addr, uint32_t length, + std::chrono::seconds timeout) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, __FUNCTION__, insert ? "add" : "remove", addr); @@ -2728,7 +2767,7 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( // or "" (unsupported) response.SetResponseValidatorToOKErrorNotSupported(); // Try to send the breakpoint packet, and check that it was correctly sent - if (SendPacketAndWaitForResponse(packet, response, true) == + if (SendPacketAndWaitForResponse(packet, response, timeout) == PacketResult::Success) { // Receive and OK packet when the breakpoint successfully placed if (response.IsOKResponse()) @@ -2766,11 +2805,12 @@ uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket( return UINT8_MAX; } -size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( - std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) { - thread_ids.clear(); +std::vector<std::pair<lldb::pid_t, lldb::tid_t>> +GDBRemoteCommunicationClient::GetCurrentProcessAndThreadIDs( + bool &sequence_mutex_unavailable) { + std::vector<std::pair<lldb::pid_t, lldb::tid_t>> ids; - Lock lock(*this, false); + Lock lock(*this); if (lock) { sequence_mutex_unavailable = false; StringExtractorGDBRemote response; @@ -2786,11 +2826,11 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( break; if (ch == 'm') { do { - tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); + auto pid_tid = response.GetPidTid(LLDB_INVALID_PROCESS_ID); + if (!pid_tid) + return {}; - if (tid != LLDB_INVALID_THREAD_ID) { - thread_ids.push_back(tid); - } + ids.push_back(pid_tid.getValue()); ch = response.GetChar(); // Skip the command separator } while (ch == ','); // Make sure we got a comma separator } @@ -2803,10 +2843,10 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( * be as simple as 'S05'. There is no packet which can give us pid and/or * tid. * Assume pid=tid=1 in such cases. - */ + */ if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) && - thread_ids.size() == 0 && IsConnected()) { - thread_ids.push_back(1); + ids.size() == 0 && IsConnected()) { + ids.emplace_back(1, 1); } } else { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS | @@ -2815,12 +2855,34 @@ size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( "packet 'qfThreadInfo'"); sequence_mutex_unavailable = true; } + + return ids; +} + +size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs( + std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) { + lldb::pid_t pid = GetCurrentProcessID(); + thread_ids.clear(); + + auto ids = GetCurrentProcessAndThreadIDs(sequence_mutex_unavailable); + if (ids.empty() || sequence_mutex_unavailable) + return 0; + + for (auto id : ids) { + // skip threads that do not belong to the current process + if (id.first != LLDB_INVALID_PROCESS_ID && id.first != pid) + continue; + if (id.second != LLDB_INVALID_THREAD_ID && + id.second != StringExtractorGDBRemote::AllThreads) + thread_ids.push_back(id.second); + } + return thread_ids.size(); } lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) != + if (SendPacketAndWaitForResponse("qShlibInfoAddr", response) != PacketResult::Success || !response.IsNormalResponse()) return LLDB_INVALID_ADDRESS; @@ -2853,7 +2915,7 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand( stream.PutStringAsRawHex8(path); } StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return Status("malformed reply"); @@ -2891,8 +2953,7 @@ Status GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec, llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success) return Status("failed to send '%s' packet", packet.str().c_str()); if (response.GetChar() != 'F') @@ -2913,8 +2974,7 @@ GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec, llvm::StringRef packet = stream.GetString(); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet, response, false) != - PacketResult::Success) + if (SendPacketAndWaitForResponse(packet, response) != PacketResult::Success) return Status("failed to send '%s' packet", stream.GetData()); if (response.GetChar() != 'F') @@ -2956,7 +3016,7 @@ GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec, stream.PutChar(','); stream.PutHex32(mode); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { return ParseHostIOPacketResponse(response, UINT64_MAX, error); } @@ -2968,7 +3028,7 @@ bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, lldb_private::StreamString stream; stream.Printf("vFile:close:%i", (int)fd); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { return ParseHostIOPacketResponse(response, -1, error) == 0; } @@ -2983,7 +3043,7 @@ lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize( stream.PutCString("vFile:size:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return UINT64_MAX; @@ -3001,7 +3061,7 @@ void GDBRemoteCommunicationClient::AutoCompleteDiskFileOrDirectory( stream.PutChar(','); stream.PutStringAsRawHex8(request.GetCursorArgumentPrefix()); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { StreamString strm; char ch = response.GetChar(); @@ -3027,7 +3087,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec, stream.PutCString("vFile:mode:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("invalid response to '%s' packet", @@ -3062,7 +3122,7 @@ uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd, stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return 0; @@ -3096,7 +3156,7 @@ uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd, stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset); stream.PutEscapedBytes(src, src_len); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') { error.SetErrorStringWithFormat("write file failed"); @@ -3131,7 +3191,7 @@ Status GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, stream.PutChar(','); stream.PutStringAsRawHex8(src_path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); @@ -3162,7 +3222,7 @@ Status GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) { // so we follow suit here stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() == 'F') { uint32_t result = response.GetU32(UINT32_MAX); @@ -3192,7 +3252,7 @@ bool GDBRemoteCommunicationClient::GetFileExists( stream.PutCString("vFile:exists:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return false; @@ -3211,7 +3271,7 @@ bool GDBRemoteCommunicationClient::CalculateMD5( stream.PutCString("vFile:MD5:"); stream.PutStringAsRawHex8(path); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(stream.GetString(), response, false) == + if (SendPacketAndWaitForResponse(stream.GetString(), response) == PacketResult::Success) { if (response.GetChar() != 'F') return false; @@ -3258,7 +3318,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, payload.Printf("p%x", reg); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success || + tid, std::move(payload), response) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; @@ -3273,7 +3333,7 @@ DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) { payload.PutChar('g'); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success || + tid, std::move(payload), response) != PacketResult::Success || !response.IsNormalResponse()) return nullptr; @@ -3292,9 +3352,8 @@ bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), - response, false) == - PacketResult::Success && + return SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response) == PacketResult::Success && response.IsOKResponse(); } @@ -3306,9 +3365,8 @@ bool GDBRemoteCommunicationClient::WriteAllRegisters( endian::InlHostByteOrder(), endian::InlHostByteOrder()); StringExtractorGDBRemote response; - return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), - response, false) == - PacketResult::Success && + return SendThreadSpecificPacketAndWaitForResponse( + tid, std::move(payload), response) == PacketResult::Success && response.IsOKResponse(); } @@ -3323,7 +3381,7 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid, payload.PutCString("QSaveRegisterState"); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success) + tid, std::move(payload), response) != PacketResult::Success) return false; if (response.IsUnsupportedResponse()) @@ -3349,7 +3407,7 @@ bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid, payload.Printf("QRestoreRegisterState:%u", save_id); StringExtractorGDBRemote response; if (SendThreadSpecificPacketAndWaitForResponse( - tid, std::move(payload), response, false) != PacketResult::Success) + tid, std::move(payload), response) != PacketResult::Success) return false; if (response.IsOKResponse()) @@ -3367,251 +3425,179 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { StreamString packet; StringExtractorGDBRemote response; packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid); - return SendPacketAndWaitForResponse(packet.GetString(), response, false) == + return SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success && response.IsOKResponse(); } -lldb::user_id_t -GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, - Status &error) { +llvm::Expected<TraceSupportedResponse> +GDBRemoteCommunicationClient::SendTraceSupported(std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - lldb::user_id_t ret_uid = LLDB_INVALID_UID; StreamGDBRemote escaped_packet; - escaped_packet.PutCString("jTraceStart:"); - - StructuredData::Dictionary json_packet; - json_packet.AddIntegerItem("type", options.getType()); - json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); - json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); - - if (options.getThreadID() != LLDB_INVALID_THREAD_ID) - json_packet.AddIntegerItem("threadid", options.getThreadID()); - - StructuredData::DictionarySP custom_params = options.getTraceParams(); - if (custom_params) - json_packet.AddItem("params", custom_params); - - StreamString json_string; - json_packet.Dump(json_string, false); - escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + escaped_packet.PutCString("jLLDBTraceSupported"); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { - if (!response.IsNormalResponse()) { - error = response.GetStatus(); - LLDB_LOG(log, "Target does not support Tracing , error {0}", error); - } else { - ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); - } - } else { - LLDB_LOG(log, "failed to send packet"); - error.SetErrorStringWithFormat("failed to send packet: '%s'", - escaped_packet.GetData()); + if (response.IsErrorResponse()) + return response.GetStatus().ToError(); + if (response.IsUnsupportedResponse()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "jLLDBTraceSupported is unsupported"); + + return llvm::json::parse<TraceSupportedResponse>(response.Peek(), + "TraceSupportedResponse"); } - return ret_uid; + LLDB_LOG(log, "failed to send packet: jLLDBTraceSupported"); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceSupported"); } -Status -GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid, - lldb::tid_t thread_id) { +llvm::Error +GDBRemoteCommunicationClient::SendTraceStop(const TraceStopRequest &request, + std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - StringExtractorGDBRemote response; - Status error; - StructuredData::Dictionary json_packet; StreamGDBRemote escaped_packet; - StreamString json_string; - escaped_packet.PutCString("jTraceStop:"); - - json_packet.AddIntegerItem("traceid", uid); + escaped_packet.PutCString("jLLDBTraceStop:"); - if (thread_id != LLDB_INVALID_THREAD_ID) - json_packet.AddIntegerItem("threadid", thread_id); + std::string json_string; + llvm::raw_string_ostream os(json_string); + os << toJSON(request); + os.flush(); - json_packet.Dump(json_string, false); - - escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size()); + StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { - if (!response.IsOKResponse()) { - error = response.GetStatus(); - LLDB_LOG(log, "stop tracing failed"); - } - } else { - LLDB_LOG(log, "failed to send packet"); - error.SetErrorStringWithFormat( - "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(), - response.GetError()); + if (response.IsErrorResponse()) + return response.GetStatus().ToError(); + if (response.IsUnsupportedResponse()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "jLLDBTraceStop is unsupported"); + if (response.IsOKResponse()) + return llvm::Error::success(); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid jLLDBTraceStart response"); } - return error; + LLDB_LOG(log, "failed to send packet: jLLDBTraceStop"); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceStop '%s'", + escaped_packet.GetData()); } -Status GDBRemoteCommunicationClient::SendGetDataPacket( - lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { +llvm::Error +GDBRemoteCommunicationClient::SendTraceStart(const llvm::json::Value ¶ms, + std::chrono::seconds timeout) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); StreamGDBRemote escaped_packet; - escaped_packet.PutCString("jTraceBufferRead:"); - return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); -} - -Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( - lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { + escaped_packet.PutCString("jLLDBTraceStart:"); - StreamGDBRemote escaped_packet; - escaped_packet.PutCString("jTraceMetaRead:"); - return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); -} + std::string json_string; + llvm::raw_string_ostream os(json_string); + os << params; + os.flush(); -llvm::Expected<TraceTypeInfo> -GDBRemoteCommunicationClient::SendGetSupportedTraceType() { - Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - - StreamGDBRemote escaped_packet; - escaped_packet.PutCString("jLLDBTraceSupportedType"); + escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size()); StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsErrorResponse()) return response.GetStatus().ToError(); if (response.IsUnsupportedResponse()) return llvm::createStringError(llvm::inconvertibleErrorCode(), - "jLLDBTraceSupportedType is unsupported"); - - if (llvm::Expected<TraceTypeInfo> type = - llvm::json::parse<TraceTypeInfo>(response.Peek())) - return *type; - else - return type.takeError(); + "jLLDBTraceStart is unsupported"); + if (response.IsOKResponse()) + return llvm::Error::success(); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Invalid jLLDBTraceStart response"); } - LLDB_LOG(log, "failed to send packet: jLLDBTraceSupportedType"); - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "failed to send packet: jLLDBTraceSupportedType"); + LLDB_LOG(log, "failed to send packet: jLLDBTraceStart"); + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceStart '%s'", + escaped_packet.GetData()); } -Status -GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, - TraceOptions &options) { +llvm::Expected<std::string> +GDBRemoteCommunicationClient::SendTraceGetState(llvm::StringRef type, + std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - StringExtractorGDBRemote response; - Status error; - StreamString json_string; StreamGDBRemote escaped_packet; - escaped_packet.PutCString("jTraceConfigRead:"); - - StructuredData::Dictionary json_packet; - json_packet.AddIntegerItem("traceid", uid); + escaped_packet.PutCString("jLLDBTraceGetState:"); - if (options.getThreadID() != LLDB_INVALID_THREAD_ID) - json_packet.AddIntegerItem("threadid", options.getThreadID()); + std::string json_string; + llvm::raw_string_ostream os(json_string); + os << toJSON(TraceGetStateRequest{type.str()}); + os.flush(); - json_packet.Dump(json_string, false); - escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size()); + StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, - true) == + timeout) == GDBRemoteCommunication::PacketResult::Success) { - if (response.IsNormalResponse()) { - uint64_t type = std::numeric_limits<uint64_t>::max(); - uint64_t buffersize = std::numeric_limits<uint64_t>::max(); - uint64_t metabuffersize = std::numeric_limits<uint64_t>::max(); - - auto json_object = StructuredData::ParseJSON(response.Peek()); - - if (!json_object || - json_object->GetType() != lldb::eStructuredDataTypeDictionary) { - error.SetErrorString("Invalid Configuration obtained"); - return error; - } - - auto json_dict = json_object->GetAsDictionary(); - - json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize", - metabuffersize); - options.setMetaDataBufferSize(metabuffersize); - - json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize); - options.setTraceBufferSize(buffersize); - - json_dict->GetValueForKeyAsInteger<uint64_t>("type", type); - options.setType(static_cast<lldb::TraceType>(type)); - - StructuredData::ObjectSP custom_params_sp = - json_dict->GetValueForKey("params"); - if (custom_params_sp) { - if (custom_params_sp->GetType() != - lldb::eStructuredDataTypeDictionary) { - error.SetErrorString("Invalid Configuration obtained"); - return error; - } else - options.setTraceParams( - std::static_pointer_cast<StructuredData::Dictionary>( - custom_params_sp)); - } - } else { - error = response.GetStatus(); - } - } else { - LLDB_LOG(log, "failed to send packet"); - error.SetErrorStringWithFormat("failed to send packet: '%s'", - escaped_packet.GetData()); + if (response.IsErrorResponse()) + return response.GetStatus().ToError(); + if (response.IsUnsupportedResponse()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "jLLDBTraceGetState is unsupported"); + return std::string(response.Peek()); } - return error; + + LLDB_LOG(log, "failed to send packet: jLLDBTraceGetState"); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceGetState '%s'", + escaped_packet.GetData()); } -Status GDBRemoteCommunicationClient::SendGetTraceDataPacket( - StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) { +llvm::Expected<std::vector<uint8_t>> +GDBRemoteCommunicationClient::SendTraceGetBinaryData( + const TraceGetBinaryDataRequest &request, std::chrono::seconds timeout) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - Status error; - StructuredData::Dictionary json_packet; - - json_packet.AddIntegerItem("traceid", uid); - json_packet.AddIntegerItem("offset", offset); - json_packet.AddIntegerItem("buffersize", buffer.size()); + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jLLDBTraceGetBinaryData:"); - if (thread_id != LLDB_INVALID_THREAD_ID) - json_packet.AddIntegerItem("threadid", thread_id); + std::string json_string; + llvm::raw_string_ostream os(json_string); + os << toJSON(request); + os.flush(); - StreamString json_string; - json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.c_str(), json_string.size()); - packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, true) == + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + timeout) == GDBRemoteCommunication::PacketResult::Success) { - if (response.IsNormalResponse()) { - size_t filled_size = response.GetHexBytesAvail(buffer); - buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size); - } else { - error = response.GetStatus(); - buffer = buffer.slice(buffer.size()); - } - } else { - LLDB_LOG(log, "failed to send packet"); - error.SetErrorStringWithFormat("failed to send packet: '%s'", - packet.GetData()); - buffer = buffer.slice(buffer.size()); + if (response.IsErrorResponse()) + return response.GetStatus().ToError(); + if (response.IsUnsupportedResponse()) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "jLLDBTraceGetBinaryData is unsupported"); + std::string data; + response.GetEscapedBinaryData(data); + return std::vector<uint8_t>(data.begin(), data.end()); } - return error; + LLDB_LOG(log, "failed to send packet: jLLDBTraceGetBinaryData"); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceGetBinaryData '%s'", + escaped_packet.GetData()); } llvm::Optional<QOffsets> GDBRemoteCommunicationClient::GetQOffsets() { StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse( - "qOffsets", response, /*send_async=*/false) != PacketResult::Success) + if (SendPacketAndWaitForResponse("qOffsets", response) != + PacketResult::Success) return llvm::None; if (!response.IsNormalResponse()) return llvm::None; @@ -3666,7 +3652,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo( packet.PutStringAsRawHex8(triple); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(packet.GetString(), response, false) != + if (SendPacketAndWaitForResponse(packet.GetString(), response) != PacketResult::Success) return false; @@ -3773,7 +3759,7 @@ GDBRemoteCommunicationClient::GetModulesInfo( ScopedTimeout timeout(*this, std::chrono::seconds(10)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse(payload.GetString(), response, false) != + if (SendPacketAndWaitForResponse(payload.GetString(), response) != PacketResult::Success || response.IsErrorResponse()) return llvm::None; @@ -3832,7 +3818,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature( << "," << std::hex << size; GDBRemoteCommunication::PacketResult res = - SendPacketAndWaitForResponse(packet.str(), chunk, false); + SendPacketAndWaitForResponse(packet.str(), chunk); if (res != GDBRemoteCommunication::PacketResult::Success) { err.SetErrorString("Error sending $qXfer packet"); @@ -3921,7 +3907,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups( bool first_qsymbol_query = true; if (m_supports_qSymbol && !m_qSymbol_requests_done) { - Lock lock(*this, false); + Lock lock(*this); if (lock) { StreamString packet; packet.PutCString("qSymbol::"); @@ -4049,9 +4035,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() { // Poll it now. StringExtractorGDBRemote response; - const bool send_async = false; - if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response, - send_async) == PacketResult::Success) { + if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response) == + PacketResult::Success) { m_supported_async_json_packets_sp = StructuredData::ParseJSON(std::string(response.GetStringRef())); if (m_supported_async_json_packets_sp && @@ -4095,7 +4080,7 @@ Status GDBRemoteCommunicationClient::SendSignalsToIgnore( std::string packet = formatv("QPassSignals:{0:$[;]@(x-2)}", range).str(); StringExtractorGDBRemote response; - auto send_status = SendPacketAndWaitForResponse(packet, response, false); + auto send_status = SendPacketAndWaitForResponse(packet, response); if (send_status != GDBRemoteCommunication::PacketResult::Success) return Status("Sending QPassSignals packet failed"); @@ -4134,10 +4119,8 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData( stream.Flush(); // Send the packet. - const bool send_async = false; StringExtractorGDBRemote response; - auto result = - SendPacketAndWaitForResponse(stream.GetString(), response, send_async); + auto result = SendPacketAndWaitForResponse(stream.GetString(), response); if (result == PacketResult::Success) { // We failed if the config result comes back other than OK. if (strcmp(response.GetStringRef().data(), "OK") == 0) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index af3755fce774..1e1797c10dfc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -22,7 +22,7 @@ #include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/StructuredData.h" -#include "lldb/Utility/TraceOptions.h" +#include "lldb/Utility/TraceGDBRemotePackets.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" #endif @@ -49,6 +49,12 @@ inline bool operator==(const QOffsets &a, const QOffsets &b) { } llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const QOffsets &offsets); +// A trivial struct used to return a pair of PID and TID. +struct PidTid { + uint64_t pid; + uint64_t tid; +}; + class GDBRemoteCommunicationClient : public GDBRemoteClientBase { public: GDBRemoteCommunicationClient(); @@ -275,6 +281,8 @@ public: ArchSpec GetSystemArchitecture(); + uint32_t GetAddressingBits(); + bool GetHostname(std::string &s); lldb::addr_t GetShlibInfoAddr(); @@ -319,7 +327,8 @@ public: GDBStoppointType type, // Type of breakpoint or watchpoint bool insert, // Insert or remove? lldb::addr_t addr, // Address of breakpoint or watchpoint - uint32_t length); // Byte Size of breakpoint or watchpoint + uint32_t length, // Byte Size of breakpoint or watchpoint + std::chrono::seconds interrupt_timeout); // Time to wait for an interrupt bool SetNonStopMode(const bool enable); @@ -334,9 +343,14 @@ public: // and response times. bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size); - bool SetCurrentThread(uint64_t tid); + llvm::Optional<PidTid> + SendSetCurrentThreadPacket(uint64_t tid, uint64_t pid, char op); - bool SetCurrentThreadForRun(uint64_t tid); + bool SetCurrentThread(uint64_t tid, + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); + + bool SetCurrentThreadForRun(uint64_t tid, + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); bool GetQXferAuxvReadSupported(); @@ -366,6 +380,9 @@ public: return m_supports_alloc_dealloc_memory; } + std::vector<std::pair<lldb::pid_t, lldb::tid_t>> + GetCurrentProcessAndThreadIDs(bool &sequence_mutex_unavailable); + size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable); @@ -446,6 +463,14 @@ public: bool GetSharedCacheInfoSupported(); + bool GetMemoryTaggingSupported(); + + lldb::DataBufferSP ReadMemoryTags(lldb::addr_t addr, size_t len, + int32_t type); + + Status WriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type, + const std::vector<uint8_t> &tags); + /// Use qOffsets to query the offset used when relocating the target /// executable. If successful, the returned structure will contain at least /// one value in the offsets field. @@ -505,59 +530,61 @@ public: ConfigureRemoteStructuredData(ConstString type_name, const StructuredData::ObjectSP &config_sp); - lldb::user_id_t SendStartTracePacket(const TraceOptions &options, - Status &error); + llvm::Expected<TraceSupportedResponse> + SendTraceSupported(std::chrono::seconds interrupt_timeout); - Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id); + llvm::Error SendTraceStart(const llvm::json::Value &request, + std::chrono::seconds interrupt_timeout); - Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0); + llvm::Error SendTraceStop(const TraceStopRequest &request, + std::chrono::seconds interrupt_timeout); - Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0); + llvm::Expected<std::string> + SendTraceGetState(llvm::StringRef type, + std::chrono::seconds interrupt_timeout); - Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); - - llvm::Expected<TraceTypeInfo> SendGetSupportedTraceType(); + llvm::Expected<std::vector<uint8_t>> + SendTraceGetBinaryData(const TraceGetBinaryDataRequest &request, + std::chrono::seconds interrupt_timeout); protected: - LazyBool m_supports_not_sending_acks; - LazyBool m_supports_thread_suffix; - LazyBool m_supports_threads_in_stop_reply; - LazyBool m_supports_vCont_all; - LazyBool m_supports_vCont_any; - LazyBool m_supports_vCont_c; - LazyBool m_supports_vCont_C; - LazyBool m_supports_vCont_s; - LazyBool m_supports_vCont_S; - LazyBool m_qHostInfo_is_valid; - LazyBool m_curr_pid_is_valid; - LazyBool m_qProcessInfo_is_valid; - LazyBool m_qGDBServerVersion_is_valid; - LazyBool m_supports_alloc_dealloc_memory; - LazyBool m_supports_memory_region_info; - LazyBool m_supports_watchpoint_support_info; - LazyBool m_supports_detach_stay_stopped; - LazyBool m_watchpoints_trigger_after_instruction; - LazyBool m_attach_or_wait_reply; - LazyBool m_prepare_for_reg_writing_reply; - LazyBool m_supports_p; - LazyBool m_supports_x; - LazyBool m_avoid_g_packets; - LazyBool m_supports_QSaveRegisterState; - LazyBool m_supports_qXfer_auxv_read; - LazyBool m_supports_qXfer_libraries_read; - LazyBool m_supports_qXfer_libraries_svr4_read; - LazyBool m_supports_qXfer_features_read; - LazyBool m_supports_qXfer_memory_map_read; - LazyBool m_supports_augmented_libraries_svr4_read; - LazyBool m_supports_jThreadExtendedInfo; - LazyBool m_supports_jLoadedDynamicLibrariesInfos; - LazyBool m_supports_jGetSharedCacheInfo; - LazyBool m_supports_QPassSignals; - LazyBool m_supports_error_string_reply; + LazyBool m_supports_not_sending_acks = eLazyBoolCalculate; + LazyBool m_supports_thread_suffix = eLazyBoolCalculate; + LazyBool m_supports_threads_in_stop_reply = eLazyBoolCalculate; + LazyBool m_supports_vCont_all = eLazyBoolCalculate; + LazyBool m_supports_vCont_any = eLazyBoolCalculate; + LazyBool m_supports_vCont_c = eLazyBoolCalculate; + LazyBool m_supports_vCont_C = eLazyBoolCalculate; + LazyBool m_supports_vCont_s = eLazyBoolCalculate; + LazyBool m_supports_vCont_S = eLazyBoolCalculate; + LazyBool m_qHostInfo_is_valid = eLazyBoolCalculate; + LazyBool m_curr_pid_is_valid = eLazyBoolCalculate; + LazyBool m_qProcessInfo_is_valid = eLazyBoolCalculate; + LazyBool m_qGDBServerVersion_is_valid = eLazyBoolCalculate; + LazyBool m_supports_alloc_dealloc_memory = eLazyBoolCalculate; + LazyBool m_supports_memory_region_info = eLazyBoolCalculate; + LazyBool m_supports_watchpoint_support_info = eLazyBoolCalculate; + LazyBool m_supports_detach_stay_stopped = eLazyBoolCalculate; + LazyBool m_watchpoints_trigger_after_instruction = eLazyBoolCalculate; + LazyBool m_attach_or_wait_reply = eLazyBoolCalculate; + LazyBool m_prepare_for_reg_writing_reply = eLazyBoolCalculate; + LazyBool m_supports_p = eLazyBoolCalculate; + LazyBool m_supports_x = eLazyBoolCalculate; + LazyBool m_avoid_g_packets = eLazyBoolCalculate; + LazyBool m_supports_QSaveRegisterState = eLazyBoolCalculate; + LazyBool m_supports_qXfer_auxv_read = eLazyBoolCalculate; + LazyBool m_supports_qXfer_libraries_read = eLazyBoolCalculate; + LazyBool m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; + LazyBool m_supports_qXfer_features_read = eLazyBoolCalculate; + LazyBool m_supports_qXfer_memory_map_read = eLazyBoolCalculate; + LazyBool m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; + LazyBool m_supports_jThreadExtendedInfo = eLazyBoolCalculate; + LazyBool m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolCalculate; + LazyBool m_supports_jGetSharedCacheInfo = eLazyBoolCalculate; + LazyBool m_supports_QPassSignals = eLazyBoolCalculate; + LazyBool m_supports_error_string_reply = eLazyBoolCalculate; + LazyBool m_supports_multiprocess = eLazyBoolCalculate; + LazyBool m_supports_memory_tagging = eLazyBoolCalculate; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, @@ -568,13 +595,17 @@ protected: m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1, m_supports_jModulesInfo : 1; - lldb::pid_t m_curr_pid; - lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all - // other operations - lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for - // continue, step, etc + /// Current gdb remote protocol process identifier for all other operations + lldb::pid_t m_curr_pid = LLDB_INVALID_PROCESS_ID; + /// Current gdb remote protocol process identifier for continue, step, etc + lldb::pid_t m_curr_pid_run = LLDB_INVALID_PROCESS_ID; + /// Current gdb remote protocol thread identifier for all other operations + lldb::tid_t m_curr_tid = LLDB_INVALID_THREAD_ID; + /// Current gdb remote protocol thread identifier for continue, step, etc + lldb::tid_t m_curr_tid_run = LLDB_INVALID_THREAD_ID; - uint32_t m_num_supported_hardware_watchpoints; + uint32_t m_num_supported_hardware_watchpoints = 0; + uint32_t m_addressing_bits = 0; ArchSpec m_host_arch; ArchSpec m_process_arch; @@ -585,17 +616,19 @@ protected: std::string m_hostname; std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if // qGDBServerVersion is not supported - uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if - // qGDBServerVersion is not supported + uint32_t m_gdb_server_version = + UINT32_MAX; // from reply to qGDBServerVersion, zero if + // qGDBServerVersion is not supported std::chrono::seconds m_default_packet_timeout; - uint64_t m_max_packet_size; // as returned by qSupported + int m_target_vm_page_size = 0; // target system VM page size; 0 unspecified + uint64_t m_max_packet_size = 0; // as returned by qSupported std::string m_qSupported_response; // the complete response to qSupported - bool m_supported_async_json_packets_is_valid; + bool m_supported_async_json_packets_is_valid = false; lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp; std::vector<MemoryRegionInfo> m_qXfer_memory_map; - bool m_qXfer_memory_map_loaded; + bool m_qXfer_memory_map_loaded = false; bool GetCurrentProcessInfo(bool allow_lazy_pid = true); @@ -603,7 +636,8 @@ protected: // Given the list of compression types that the remote debug stub can support, // possibly enable compression if we find an encoding we can handle. - void MaybeEnableCompression(std::vector<std::string> supported_compressions); + void MaybeEnableCompression( + llvm::ArrayRef<llvm::StringRef> supported_compressions); bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info); @@ -612,7 +646,7 @@ protected: PacketResult SendThreadSpecificPacketAndWaitForResponse( lldb::tid_t tid, StreamString &&payload, - StringExtractorGDBRemote &response, bool send_async); + StringExtractorGDBRemote &response); Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp index 3984a45c3da1..d92c97e81659 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp @@ -19,13 +19,12 @@ using namespace lldb_private; using namespace lldb_private::process_gdb_remote; GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size) - : m_packets(), m_curr_idx(0), m_total_packet_count(0), - m_dumped_to_log(false) { + : m_packets() { if (size) m_packets.resize(size); } -GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {} +GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() = default; void GDBRemoteCommunicationHistory::AddPacket(char packet_char, GDBRemotePacket::Type type, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h index e783e59c3455..eda464a758e4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h @@ -74,9 +74,9 @@ private: } std::vector<GDBRemotePacket> m_packets; - uint32_t m_curr_idx; - uint32_t m_total_packet_count; - mutable bool m_dumped_to_log; + uint32_t m_curr_idx = 0; + uint32_t m_total_packet_count = 0; + mutable bool m_dumped_to_log = false; repro::PacketRecorder *m_recorder = nullptr; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 920327e7d0ab..c91d7cb5ac30 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <errno.h> +#include <cerrno> #include "lldb/Host/Config.h" #include "llvm/ADT/ScopeExit.h" @@ -74,7 +74,7 @@ GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer() m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.gdb-replay.async-listener")), - m_async_thread_state_mutex(), m_skip_acks(false) { + m_async_thread_state_mutex() { m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h index c13e5ee0bf92..2f8770d0accf 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h @@ -73,7 +73,7 @@ protected: HostThread m_async_thread; std::recursive_mutex m_async_thread_state_mutex; - bool m_skip_acks; + bool m_skip_acks = false; private: GDBRemoteCommunicationReplayServer( diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 60548efc0f33..11cac9fa3a4d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <errno.h> +#include <cerrno> #include "lldb/Host/Config.h" @@ -16,11 +16,13 @@ #include "lldb/Utility/StreamString.h" #include "lldb/Utility/StringExtractorGDBRemote.h" #include "lldb/Utility/UnimplementedError.h" +#include "llvm/Support/JSON.h" #include <cstring> using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +using namespace llvm; GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( const char *comm_name, const char *listener_name) @@ -31,7 +33,7 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( bool &quit) { return this->Handle_QErrorStringEnable(packet); }); } -GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} +GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default; void GDBRemoteCommunicationServer::RegisterPacketHandler( StringExtractorGDBRemote::ServerPacketType packet_type, @@ -151,3 +153,21 @@ GDBRemoteCommunicationServer::SendOKResponse() { bool GDBRemoteCommunicationServer::HandshakeWithClient() { return GetAck() == PacketResult::Success; } + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) { + std::string json_string; + raw_string_ostream os(json_string); + os << value; + os.flush(); + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size()); + return SendPacketNoLock(escaped_response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) { + if (!value) + return SendErrorResponse(value.takeError()); + return SendJSONResponse(*value); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index a1cf70f9cd1a..68448eae2b9f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -72,6 +72,13 @@ protected: PacketResult SendOKResponse(); + /// Serialize and send a JSON object response. + PacketResult SendJSONResponse(const llvm::json::Value &value); + + /// Serialize and send a JSON object response, or respond with an error if the + /// input object is an \a llvm::Error. + PacketResult SendJSONResponse(llvm::Expected<llvm::json::Value> value); + private: GDBRemoteCommunicationServer(const GDBRemoteCommunicationServer &) = delete; const GDBRemoteCommunicationServer & diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 1ca0290eda13..b2b802552720 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -8,7 +8,7 @@ #include "GDBRemoteCommunicationServerCommon.h" -#include <errno.h> +#include <cerrno> #ifdef __APPLE__ #include <TargetConditionals.h> @@ -60,8 +60,7 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( const char *comm_name, const char *listener_name) : GDBRemoteCommunicationServer(comm_name, listener_name), m_process_launch_info(), m_process_launch_error(), m_proc_infos(), - m_proc_infos_index(0), m_thread_suffix_supported(false), - m_list_threads_in_stop_reply(false) { + m_proc_infos_index(0) { RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A, &GDBRemoteCommunicationServerCommon::Handle_A); RegisterMemberFunctionHandler( @@ -86,9 +85,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, - &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply); - RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qEcho, &GDBRemoteCommunicationServerCommon::Handle_qEcho); RegisterMemberFunctionHandler( @@ -134,9 +130,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( StringExtractorGDBRemote::eServerPacketType_qSupported, &GDBRemoteCommunicationServerCommon::Handle_qSupported); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, - &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported); - RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qUserName, &GDBRemoteCommunicationServerCommon::Handle_qUserName); RegisterMemberFunctionHandler( @@ -175,7 +168,8 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( } // Destructor -GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {} +GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() = + default; GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qHostInfo( @@ -831,39 +825,10 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qSupported( StringExtractorGDBRemote &packet) { - StreamGDBRemote response; - - // Features common to lldb-platform and llgs. - uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet - // size--debugger can always use less - response.Printf("PacketSize=%x", max_packet_size); - - response.PutCString(";QStartNoAckMode+"); - response.PutCString(";QThreadSuffixSupported+"); - response.PutCString(";QListThreadsInStopReply+"); - response.PutCString(";qEcho+"); - response.PutCString(";qXfer:features:read+"); -#if defined(__linux__) || defined(__NetBSD__) || defined(__FreeBSD__) - response.PutCString(";QPassSignals+"); - response.PutCString(";qXfer:auxv:read+"); - response.PutCString(";qXfer:libraries-svr4:read+"); -#endif - - return SendPacketNoLock(response.GetString()); -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported( - StringExtractorGDBRemote &packet) { - m_thread_suffix_supported = true; - return SendOKResponse(); -} - -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply( - StringExtractorGDBRemote &packet) { - m_list_threads_in_stop_reply = true; - return SendOKResponse(); + // Parse client-indicated features. + llvm::SmallVector<llvm::StringRef, 4> client_features; + packet.GetStringRef().split(client_features, ';'); + return SendPacketNoLock(llvm::join(HandleFeatures(client_features), ";")); } GDBRemoteCommunication::PacketResult @@ -1311,3 +1276,16 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path, return matched_module_spec; } + +std::vector<std::string> GDBRemoteCommunicationServerCommon::HandleFeatures( + const llvm::ArrayRef<llvm::StringRef> client_features) { + // 128KBytes is a reasonable max packet size--debugger can always use less. + constexpr uint32_t max_packet_size = 128 * 1024; + + // Features common to platform server and llgs. + return { + llvm::formatv("PacketSize={0}", max_packet_size), + "QStartNoAckMode+", + "qEcho+", + }; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 0f933c09cbd4..ecd80923fcf0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -36,8 +36,6 @@ protected: Status m_process_launch_error; ProcessInstanceInfoList m_proc_infos; uint32_t m_proc_infos_index; - bool m_thread_suffix_supported; - bool m_list_threads_in_stop_reply; PacketResult Handle_A(StringExtractorGDBRemote &packet); @@ -91,10 +89,6 @@ protected: PacketResult Handle_qSupported(StringExtractorGDBRemote &packet); - PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet); - - PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet); - PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet); PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet); @@ -145,6 +139,11 @@ protected: virtual FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch); + // Process client_features (qSupported) and return an array of server features + // to be returned in response. + virtual std::vector<std::string> + HandleFeatures(llvm::ArrayRef<llvm::StringRef> client_features); + private: ModuleSpec GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple); }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 62a09a2a432c..5e69b5793f9f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -6,13 +6,14 @@ // //===----------------------------------------------------------------------===// -#include <errno.h> +#include <cerrno> #include "lldb/Host/Config.h" #include <chrono> #include <cstring> +#include <limits> #include <thread> #include "GDBRemoteCommunicationServerLLGS.h" @@ -70,6 +71,7 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), m_mainloop(mainloop), m_process_factory(process_factory), + m_current_process(nullptr), m_continue_process(nullptr), m_stdio_communication("process.stdio") { RegisterPacketHandlers(); } @@ -113,6 +115,12 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported, + &GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply, + &GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply); + RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); RegisterMemberFunctionHandler( @@ -186,27 +194,32 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jTraceStart, - &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupported, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead, - &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStart, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead, - &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceStop, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jTraceStop, - &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop); + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetState, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState); RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, - &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); - RegisterMemberFunctionHandler( - StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType, - &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType); + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceGetBinaryData, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, &GDBRemoteCommunicationServerLLGS::Handle_g); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qMemTags, + &GDBRemoteCommunicationServerLLGS::Handle_qMemTags); + + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QMemTags, + &GDBRemoteCommunicationServerLLGS::Handle_QMemTags); + RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, bool &quit) { @@ -245,15 +258,18 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { { std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); - assert(!m_debugged_process_up && "lldb-server creating debugged " - "process but one already exists"); + assert(m_debugged_processes.empty() && "lldb-server creating debugged " + "process but one already exists"); auto process_or = m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); if (!process_or) return Status(process_or.takeError()); - m_debugged_process_up = std::move(*process_or); + m_continue_process = m_current_process = process_or->get(); + m_debugged_processes[m_current_process->GetID()] = std::move(*process_or); } + SetEnabledExtensions(*m_current_process); + // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as // needed. llgs local-process debugging may specify PTY paths, which will // make these file actions non-null process launch -i/e/o will also make @@ -266,10 +282,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { LLDB_LOG(log, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", - m_debugged_process_up->GetID()); + m_current_process->GetID()); // Setup stdout/stderr mapping from inferior to $O - auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); + auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { LLDB_LOGF(log, "ProcessGDBRemoteCommunicationServerLLGS::%s setting " @@ -288,12 +304,12 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { LLDB_LOG(log, "pid = {0} skipping stdout/stderr redirection via $O: inferior " "will communicate over client-provided file descriptors", - m_debugged_process_up->GetID()); + m_current_process->GetID()); } printf("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments().GetArgumentAtIndex(0), - m_debugged_process_up->GetID()); + m_current_process->GetID()); return Status(); } @@ -305,12 +321,11 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { // Before we try to attach, make sure we aren't already monitoring something // else. - if (m_debugged_process_up && - m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID) + if (!m_debugged_processes.empty()) return Status("cannot attach to process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", - pid, m_debugged_process_up->GetID()); + pid, m_current_process->GetID()); // Try to attach. auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); @@ -320,10 +335,12 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { status); return status; } - m_debugged_process_up = std::move(*process_or); + m_continue_process = m_current_process = process_or->get(); + m_debugged_processes[m_current_process->GetID()] = std::move(*process_or); + SetEnabledExtensions(*m_current_process); // Setup stdout/stderr mapping from inferior. - auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); + auto terminal_fd = m_current_process->GetTerminalFileDescriptor(); if (terminal_fd >= 0) { LLDB_LOGF(log, "ProcessGDBRemoteCommunicationServerLLGS::%s setting " @@ -648,6 +665,14 @@ static const char *GetStopReasonString(StopReason stop_reason) { return "exception"; case eStopReasonExec: return "exec"; + case eStopReasonProcessorTrace: + return "processor trace"; + case eStopReasonFork: + return "fork"; + case eStopReasonVFork: + return "vfork"; + case eStopReasonVForkDone: + return "vforkdone"; case eStopReasonInstrumentation: case eStopReasonInvalid: case eStopReasonPlanComplete: @@ -736,15 +761,15 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); LLDB_LOG(log, "preparing packet for pid {0} tid {1}", - m_debugged_process_up->GetID(), tid); + m_current_process->GetID(), tid); // Ensure we can get info on the given thread. - NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + NativeThreadProtocol *thread = m_current_process->GetThreadByID(tid); if (!thread) return SendErrorResponse(51); @@ -767,7 +792,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( LLDB_LOG( log, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}", - m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason), + m_current_process->GetID(), tid, signum, int(tid_stop_info.reason), tid_stop_info.details.exception.type); // Print the signal number. @@ -805,9 +830,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( uint32_t thread_index = 0; NativeThreadProtocol *listed_thread; - for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + for (listed_thread = m_current_process->GetThreadAtIndex(thread_index); listed_thread; ++thread_index, - listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { + listed_thread = m_current_process->GetThreadAtIndex(thread_index)) { if (thread_index > 0) response.PutChar(','); response.Printf("%" PRIx64, listed_thread->GetID()); @@ -822,7 +847,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( if (thread_index > 1) { const bool threads_with_valid_stop_info_only = true; llvm::Expected<json::Array> threads_info = GetJSONThreadsInfo( - *m_debugged_process_up, threads_with_valid_stop_info_only); + *m_current_process, threads_with_valid_stop_info_only); if (threads_info) { response.PutCString("jstopinfo:"); StreamString unescaped_response; @@ -832,7 +857,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( } else { LLDB_LOG_ERROR(log, threads_info.takeError(), "failed to prepare a jstopinfo field for pid {1}: {0}", - m_debugged_process_up->GetID()); + m_current_process->GetID()); } } @@ -840,8 +865,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( response.PutCString("thread-pcs"); char delimiter = ':'; for (NativeThreadProtocol *thread; - (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; - ++i) { + (thread = m_current_process->GetThreadAtIndex(i)) != nullptr; ++i) { NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber( @@ -924,6 +948,22 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( } } + // Include child process PID/TID for forks. + if (tid_stop_info.reason == eStopReasonFork || + tid_stop_info.reason == eStopReasonVFork) { + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::multiprocess)); + if (tid_stop_info.reason == eStopReasonFork) + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::fork)); + if (tid_stop_info.reason == eStopReasonVFork) + assert(bool(m_extensions_supported & + NativeProcessProtocol::Extension::vfork)); + response.Printf("%s:p%" PRIx64 ".%" PRIx64 ";", reason_str, + tid_stop_info.details.fork.child_pid, + tid_stop_info.details.fork.child_tid); + } + return SendPacketNoLock(response.GetString()); } @@ -1028,6 +1068,15 @@ void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { ClearProcessSpecificData(); } +void GDBRemoteCommunicationServerLLGS::NewSubprocess( + NativeProcessProtocol *parent_process, + std::unique_ptr<NativeProcessProtocol> child_process) { + lldb::pid_t child_pid = child_process->GetID(); + assert(child_pid != LLDB_INVALID_PROCESS_ID); + assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end()); + m_debugged_processes[child_pid] = std::move(child_process); +} + void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM)); @@ -1170,266 +1219,110 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupported( StringExtractorGDBRemote &packet) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse(68); - - if (!packet.ConsumeFront("jTraceStart:")) - return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); - - TraceOptions options; - uint64_t type = std::numeric_limits<uint64_t>::max(); - uint64_t buffersize = std::numeric_limits<uint64_t>::max(); - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - uint64_t metabuffersize = std::numeric_limits<uint64_t>::max(); - - auto json_object = StructuredData::ParseJSON(packet.Peek()); - - if (!json_object || - json_object->GetType() != lldb::eStructuredDataTypeDictionary) - return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); - - auto json_dict = json_object->GetAsDictionary(); - - json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); - options.setMetaDataBufferSize(metabuffersize); - json_dict->GetValueForKeyAsInteger("buffersize", buffersize); - options.setTraceBufferSize(buffersize); - - json_dict->GetValueForKeyAsInteger("type", type); - options.setType(static_cast<lldb::TraceType>(type)); - - json_dict->GetValueForKeyAsInteger("threadid", tid); - options.setThreadID(tid); - - StructuredData::ObjectSP custom_params_sp = - json_dict->GetValueForKey("params"); - if (custom_params_sp && - custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) - return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); - - options.setTraceParams( - std::static_pointer_cast<StructuredData::Dictionary>(custom_params_sp)); - - if (buffersize == std::numeric_limits<uint64_t>::max() || - type != lldb::TraceType::eTraceTypeProcessorTrace) { - LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize, - type); - return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet "); - } - - Status error; - lldb::user_id_t uid = LLDB_INVALID_UID; - uid = m_debugged_process_up->StartTrace(options, error); - LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError()); - if (error.Fail()) - return SendErrorResponse(error); + // Fail if we don't have a current process. + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(Status("Process not running.")); - StreamGDBRemote response; - response.Printf("%" PRIx64, uid); - return SendPacketNoLock(response.GetString()); + return SendJSONResponse(m_current_process->TraceSupported()); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStop( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse(68); - - if (!packet.ConsumeFront("jTraceStop:")) - return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); - - lldb::user_id_t uid = LLDB_INVALID_UID; - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - - auto json_object = StructuredData::ParseJSON(packet.Peek()); - - if (!json_object || - json_object->GetType() != lldb::eStructuredDataTypeDictionary) - return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); - - auto json_dict = json_object->GetAsDictionary(); - - if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) - return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(Status("Process not running.")); - json_dict->GetValueForKeyAsInteger("threadid", tid); + packet.ConsumeFront("jLLDBTraceStop:"); + Expected<TraceStopRequest> stop_request = + json::parse<TraceStopRequest>(packet.Peek(), "TraceStopRequest"); + if (!stop_request) + return SendErrorResponse(stop_request.takeError()); - Status error = m_debugged_process_up->StopTrace(uid, tid); - - if (error.Fail()) - return SendErrorResponse(error); + if (Error err = m_current_process->TraceStop(*stop_request)) + return SendErrorResponse(std::move(err)); return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType( +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceStart( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(Status("Process not running.")); - llvm::Expected<TraceTypeInfo> supported_trace_type = - m_debugged_process_up->GetSupportedTraceType(); - if (!supported_trace_type) - return SendErrorResponse(supported_trace_type.takeError()); + packet.ConsumeFront("jLLDBTraceStart:"); + Expected<TraceStartRequest> request = + json::parse<TraceStartRequest>(packet.Peek(), "TraceStartRequest"); + if (!request) + return SendErrorResponse(request.takeError()); - StreamGDBRemote escaped_response; - StructuredData::Dictionary json_packet; + if (Error err = m_current_process->TraceStart(packet.Peek(), request->type)) + return SendErrorResponse(std::move(err)); - json_packet.AddStringItem("name", supported_trace_type->name); - json_packet.AddStringItem("description", supported_trace_type->description); - - StreamString json_string; - json_packet.Dump(json_string, false); - escaped_response.PutEscapedBytes(json_string.GetData(), - json_string.GetSize()); - return SendPacketNoLock(escaped_response.GetString()); + return SendOKResponse(); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetState( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse(68); - - if (!packet.ConsumeFront("jTraceConfigRead:")) - return SendIllFormedResponse(packet, - "jTraceConfigRead: Ill formed packet "); - - lldb::user_id_t uid = LLDB_INVALID_UID; - lldb::tid_t threadid = LLDB_INVALID_THREAD_ID; - - auto json_object = StructuredData::ParseJSON(packet.Peek()); - - if (!json_object || - json_object->GetType() != lldb::eStructuredDataTypeDictionary) - return SendIllFormedResponse(packet, - "jTraceConfigRead: Ill formed packet "); - - auto json_dict = json_object->GetAsDictionary(); - - if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) - return SendIllFormedResponse(packet, - "jTraceConfigRead: Ill formed packet "); - - json_dict->GetValueForKeyAsInteger("threadid", threadid); - - TraceOptions options; - StreamGDBRemote response; - - options.setThreadID(threadid); - Status error = m_debugged_process_up->GetTraceConfig(uid, options); - - if (error.Fail()) - return SendErrorResponse(error); - - StreamGDBRemote escaped_response; - StructuredData::Dictionary json_packet; - - json_packet.AddIntegerItem("type", options.getType()); - json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); - json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(Status("Process not running.")); - StructuredData::DictionarySP custom_params = options.getTraceParams(); - if (custom_params) - json_packet.AddItem("params", custom_params); + packet.ConsumeFront("jLLDBTraceGetState:"); + Expected<TraceGetStateRequest> request = + json::parse<TraceGetStateRequest>(packet.Peek(), "TraceGetStateRequest"); + if (!request) + return SendErrorResponse(request.takeError()); - StreamString json_string; - json_packet.Dump(json_string, false); - escaped_response.PutEscapedBytes(json_string.GetData(), - json_string.GetSize()); - return SendPacketNoLock(escaped_response.GetString()); + return SendJSONResponse(m_current_process->TraceGetState(request->type)); } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) - return SendErrorResponse(68); - - enum PacketType { MetaData, BufferData }; - PacketType tracetype = MetaData; - - if (packet.ConsumeFront("jTraceBufferRead:")) - tracetype = BufferData; - else if (packet.ConsumeFront("jTraceMetaRead:")) - tracetype = MetaData; - else { - return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); - } - - lldb::user_id_t uid = LLDB_INVALID_UID; - - uint64_t byte_count = std::numeric_limits<uint64_t>::max(); - lldb::tid_t tid = LLDB_INVALID_THREAD_ID; - uint64_t offset = std::numeric_limits<uint64_t>::max(); - - auto json_object = StructuredData::ParseJSON(packet.Peek()); - - if (!json_object || - json_object->GetType() != lldb::eStructuredDataTypeDictionary) - return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); - - auto json_dict = json_object->GetAsDictionary(); - - if (!json_dict->GetValueForKeyAsInteger("traceid", uid) || - !json_dict->GetValueForKeyAsInteger("offset", offset) || - !json_dict->GetValueForKeyAsInteger("buffersize", byte_count)) - return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); - - json_dict->GetValueForKeyAsInteger("threadid", tid); - - // Allocate the response buffer. - std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]); - if (!buffer) - return SendErrorResponse(0x78); - - StreamGDBRemote response; - Status error; - llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count); - - if (tracetype == BufferData) - error = m_debugged_process_up->GetData(uid, tid, buf, offset); - else if (tracetype == MetaData) - error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset); - - if (error.Fail()) - return SendErrorResponse(error); + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(Status("Process not running.")); - for (auto i : buf) - response.PutHex8(i); + packet.ConsumeFront("jLLDBTraceGetBinaryData:"); + llvm::Expected<TraceGetBinaryDataRequest> request = + llvm::json::parse<TraceGetBinaryDataRequest>(packet.Peek(), + "TraceGetBinaryDataRequest"); + if (!request) + return SendErrorResponse(Status(request.takeError())); - StreamGDBRemote escaped_response; - escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); - return SendPacketNoLock(escaped_response.GetString()); + if (Expected<std::vector<uint8_t>> bytes = + m_current_process->TraceGetBinaryData(*request)) { + StreamGDBRemote response; + response.PutEscapedBytes(bytes->data(), bytes->size()); + return SendPacketNoLock(response.GetString()); + } else + return SendErrorResponse(bytes.takeError()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); - lldb::pid_t pid = m_debugged_process_up->GetID(); + lldb::pid_t pid = m_current_process->GetID(); if (pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(1); @@ -1446,16 +1339,16 @@ GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Make sure we set the current thread so g and p packets return the data the // gdb will expect. - lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); + lldb::tid_t tid = m_current_process->GetCurrentThreadID(); SetCurrentThreadID(tid); - NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread(); + NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); if (!thread) return SendErrorResponse(69); @@ -1471,15 +1364,15 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { StopSTDIOForwarding(); - if (!m_debugged_process_up) { + if (!m_current_process) { LLDB_LOG(log, "No debugged process found."); return PacketResult::Success; } - Status error = m_debugged_process_up->Kill(); + Status error = m_current_process->Kill(); if (error.Fail()) LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); // No OK response for kill packet. // return SendOKResponse (); @@ -1521,12 +1414,26 @@ GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_QThreadSuffixSupported( + StringExtractorGDBRemote &packet) { + m_thread_suffix_supported = true; + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply( + StringExtractorGDBRemote &packet) { + m_list_threads_in_stop_reply = true; + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); // Ensure we have a native process. - if (!m_debugged_process_up) { + if (!m_continue_process) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", @@ -1579,20 +1486,20 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { } else { // Send the signal to the process since we weren't targeting a specific // continue thread with the signal. - error = m_debugged_process_up->Signal(signo); + error = m_continue_process->Signal(signo); if (error.Fail()) { LLDB_LOG(log, "failed to send signal for process {0}: {1}", - m_debugged_process_up->GetID(), error); + m_continue_process->GetID(), error); return SendErrorResponse(0x52); } } // Resume the threads. - error = m_debugged_process_up->Resume(resume_actions); + error = m_continue_process->Resume(resume_actions); if (error.Fail()) { LLDB_LOG(log, "failed to resume threads for process {0}: {1}", - m_debugged_process_up->GetID(), error); + m_continue_process->GetID(), error); return SendErrorResponse(0x38); } @@ -1617,7 +1524,7 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { } // Ensure we have a native process. - if (!m_debugged_process_up) { + if (!m_continue_process) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s no debugged process " "shared pointer", @@ -1629,14 +1536,14 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { ResumeActionList actions(StateType::eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - Status error = m_debugged_process_up->Resume(actions); + Status error = m_continue_process->Resume(actions); if (error.Fail()) { - LLDB_LOG(log, "c failed for process {0}: {1}", - m_debugged_process_up->GetID(), error); + LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(), + error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID()); + LLDB_LOG(log, "continued process {0}", m_continue_process->GetID()); // No response required from continue. return PacketResult::Success; } @@ -1679,7 +1586,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( } // Ensure we have a native process. - if (!m_debugged_process_up) { + if (!m_continue_process) { LLDB_LOG(log, "no debugged process"); return SendErrorResponse(0x36); } @@ -1732,23 +1639,27 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( // Consume the separator. packet.GetChar(); - thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); - if (thread_action.tid == LLDB_INVALID_THREAD_ID) - return SendIllFormedResponse( - packet, "Could not parse thread number in vCont packet"); + llvm::Expected<lldb::tid_t> tid_ret = + ReadTid(packet, /*allow_all=*/true, m_continue_process->GetID()); + if (!tid_ret) + return SendErrorResponse(tid_ret.takeError()); + + thread_action.tid = tid_ret.get(); + if (thread_action.tid == StringExtractorGDBRemote::AllThreads) + thread_action.tid = LLDB_INVALID_THREAD_ID; } thread_actions.Append(thread_action); } - Status error = m_debugged_process_up->Resume(thread_actions); + Status error = m_continue_process->Resume(thread_actions); if (error.Fail()) { LLDB_LOG(log, "vCont failed for process {0}: {1}", - m_debugged_process_up->GetID(), error); + m_continue_process->GetID(), error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID()); + LLDB_LOG(log, "continued process {0}", m_continue_process->GetID()); // No response required from vCont. return PacketResult::Success; } @@ -1758,8 +1669,8 @@ void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { LLDB_LOG(log, "setting current thread id to {0}", tid); m_current_tid = tid; - if (m_debugged_process_up) - m_debugged_process_up->SetCurrentThreadID(m_current_tid); + if (m_current_process) + m_current_process->SetCurrentThreadID(m_current_tid); } void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { @@ -1775,10 +1686,10 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason( // Handle the $? gdbremote command. // If no process, indicate error - if (!m_debugged_process_up) + if (!m_current_process) return SendErrorResponse(02); - return SendStopReasonForState(m_debugged_process_up->GetState()); + return SendStopReasonForState(m_current_process->GetState()); } GDBRemoteCommunication::PacketResult @@ -1799,8 +1710,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( case eStateSuspended: case eStateStopped: case eStateCrashed: { - assert(m_debugged_process_up != nullptr); - lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); + assert(m_current_process != nullptr); + lldb::tid_t tid = m_current_process->GetCurrentThreadID(); // Make sure we set the current thread so g and p packets return the data // the gdb will expect. SetCurrentThreadID(tid); @@ -1810,11 +1721,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( case eStateInvalid: case eStateUnloaded: case eStateExited: - return SendWResponse(m_debugged_process_up.get()); + return SendWResponse(m_current_process); default: LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}", - m_debugged_process_up->GetID(), process_state); + m_current_process->GetID(), process_state); break; } @@ -1825,12 +1736,12 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(68); // Ensure we have a thread. - NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); + NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0); if (!thread) return SendErrorResponse(69); @@ -1925,11 +1836,11 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOG(log, "no process ({0}), returning OK", - m_debugged_process_up ? "invalid process id" - : "null m_debugged_process_up"); + m_current_process ? "invalid process id" + : "null m_current_process"); return SendOKResponse(); } @@ -1940,9 +1851,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( NativeThreadProtocol *thread; uint32_t thread_index; for (thread_index = 0, - thread = m_debugged_process_up->GetThreadAtIndex(thread_index); + thread = m_current_process->GetThreadAtIndex(thread_index); thread; ++thread_index, - thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { + thread = m_current_process->GetThreadAtIndex(thread_index)) { LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index, thread->GetID()); if (thread_index > 0) @@ -2163,9 +2074,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { // Build the reginfos response. StreamGDBRemote response; - RegisterValue reg_value( - makeArrayRef(reg_bytes, reg_size), - m_debugged_process_up->GetArchitecture().GetByteOrder()); + RegisterValue reg_value(makeArrayRef(reg_bytes, reg_size), + m_current_process->GetArchitecture().GetByteOrder()); Status error = reg_context.WriteRegister(reg_info, reg_value); if (error.Fail()) { LLDB_LOGF(log, @@ -2182,16 +2092,6 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); - // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - LLDB_LOGF( - log, - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); - return SendErrorResponse(0x15); - } - // Parse out which variant of $H is requested. packet.SetFilePos(strlen("H")); if (packet.GetBytesLeft() < 1) { @@ -2203,11 +2103,14 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { } const char h_variant = packet.GetChar(); + NativeProcessProtocol *default_process; switch (h_variant) { case 'g': + default_process = m_current_process; break; case 'c': + default_process = m_continue_process; break; default: @@ -2220,14 +2123,32 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { } // Parse out the thread number. - // FIXME return a parse success/fail value. All values are valid here. - const lldb::tid_t tid = - packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max()); + auto pid_tid = packet.GetPidTid(default_process ? default_process->GetID() + : LLDB_INVALID_PROCESS_ID); + if (!pid_tid) + return SendErrorResponse(llvm::make_error<StringError>( + inconvertibleErrorCode(), "Malformed thread-id")); + + lldb::pid_t pid = pid_tid->first; + lldb::tid_t tid = pid_tid->second; + + if (pid == StringExtractorGDBRemote::AllProcesses) + return SendUnimplementedResponse("Selecting all processes not supported"); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendErrorResponse(llvm::make_error<StringError>( + inconvertibleErrorCode(), "No current process and no PID provided")); + + // Check the process ID and find respective process instance. + auto new_process_it = m_debugged_processes.find(pid); + if (new_process_it == m_debugged_processes.end()) + return SendErrorResponse(llvm::make_error<StringError>( + inconvertibleErrorCode(), + llvm::formatv("No process with PID {0} debugged", pid))); // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { - NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid); if (!thread) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 @@ -2237,13 +2158,15 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { } } - // Now switch the given thread type. + // Now switch the given process and thread type. switch (h_variant) { case 'g': + m_current_process = new_process_it->second.get(); SetCurrentThreadID(tid); break; case 'c': + m_continue_process = new_process_it->second.get(); SetContinueThreadID(tid); break; @@ -2261,8 +2184,8 @@ GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2297,21 +2220,21 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); } // Interrupt the process. - Status error = m_debugged_process_up->Interrupt(); + Status error = m_current_process->Interrupt(); if (error.Fail()) { - LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(), + LLDB_LOG(log, "failed for process {0}: {1}", m_current_process->GetID(), error); return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID()); + LLDB_LOG(log, "stopped process {0}", m_current_process->GetID()); // No response required from stop all. return PacketResult::Success; @@ -2322,8 +2245,8 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2365,13 +2288,13 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( // Retrieve the process memory. size_t bytes_read = 0; - Status error = m_debugged_process_up->ReadMemoryWithoutTrap( + Status error = m_current_process->ReadMemoryWithoutTrap( read_addr, &buf[0], byte_count, bytes_read); if (error.Fail()) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, + __FUNCTION__, m_current_process->GetID(), read_addr, error.AsCString()); return SendErrorResponse(0x08); } @@ -2380,8 +2303,7 @@ GDBRemoteCommunicationServerLLGS::Handle_memory_read( LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", - __FUNCTION__, m_debugged_process_up->GetID(), read_addr, - byte_count); + __FUNCTION__, m_current_process->GetID(), read_addr, byte_count); return SendErrorResponse(0x08); } @@ -2403,8 +2325,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2439,8 +2361,7 @@ GDBRemoteCommunicationServerLLGS::Handle__M(StringExtractorGDBRemote &packet) { } } - llvm::Expected<addr_t> addr = - m_debugged_process_up->AllocateMemory(size, perms); + llvm::Expected<addr_t> addr = m_current_process->AllocateMemory(size, perms); if (!addr) return SendErrorResponse(addr.takeError()); @@ -2453,8 +2374,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2471,7 +2392,7 @@ GDBRemoteCommunicationServerLLGS::Handle__m(StringExtractorGDBRemote &packet) { if (addr == LLDB_INVALID_ADDRESS) return SendIllFormedResponse(packet, "Address not valid"); - if (llvm::Error Err = m_debugged_process_up->DeallocateMemory(addr)) + if (llvm::Error Err = m_current_process->DeallocateMemory(addr)) return SendErrorResponse(std::move(Err)); return SendOKResponse(); @@ -2481,8 +2402,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2531,8 +2452,7 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { LLDB_LOG(log, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", - m_debugged_process_up->GetID(), write_addr, byte_count, - convert_count); + m_current_process->GetID(), write_addr, byte_count, convert_count); return SendIllFormedResponse(packet, "M content byte length specified did " "not match hex-encoded content " "length"); @@ -2540,17 +2460,17 @@ GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { // Write the process memory. size_t bytes_written = 0; - Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0], - byte_count, bytes_written); + Status error = m_current_process->WriteMemory(write_addr, &buf[0], byte_count, + bytes_written); if (error.Fail()) { LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}", - m_debugged_process_up->GetID(), write_addr, error); + m_current_process->GetID(), write_addr, error); return SendErrorResponse(0x09); } if (bytes_written == 0) { LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes", - m_debugged_process_up->GetID(), write_addr, byte_count); + m_current_process->GetID(), write_addr, byte_count); return SendErrorResponse(0x09); } @@ -2569,8 +2489,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // Ensure we have a process running; otherwise, we can't figure this out // since we won't have a NativeProcessProtocol. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2580,8 +2500,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( // Test if we can get any region back when asking for the region around NULL. MemoryRegionInfo region_info; - const Status error = - m_debugged_process_up->GetMemoryRegionInfo(0, region_info); + const Status error = m_current_process->GetMemoryRegionInfo(0, region_info); if (error.Fail()) { // We don't support memory region info collection for this // NativeProcessProtocol. @@ -2597,8 +2516,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); // Ensure we have a process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2619,7 +2538,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( // Get the memory region info for the target address. MemoryRegionInfo region_info; const Status error = - m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info); + m_current_process->GetMemoryRegionInfo(read_addr, region_info); if (error.Fail()) { // Return the error message. @@ -2674,8 +2593,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { // Ensure we have a process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); @@ -2745,22 +2664,22 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { if (want_breakpoint) { // Try to set the breakpoint. const Status error = - m_debugged_process_up->SetBreakpoint(addr, size, want_hardware); + m_current_process->SetBreakpoint(addr, size, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x09); } else { // Try to set the watchpoint. - const Status error = m_debugged_process_up->SetWatchpoint( + const Status error = m_current_process->SetWatchpoint( addr, size, watch_flags, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x09); } } @@ -2768,8 +2687,8 @@ GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { // Ensure we have a process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); LLDB_LOG(log, "failed, no process available"); return SendErrorResponse(0x15); @@ -2833,21 +2752,21 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { if (want_breakpoint) { // Try to clear the breakpoint. const Status error = - m_debugged_process_up->RemoveBreakpoint(addr, want_hardware); + m_current_process->RemoveBreakpoint(addr, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x09); } else { // Try to clear the watchpoint. - const Status error = m_debugged_process_up->RemoveWatchpoint(addr); + const Status error = m_current_process->RemoveWatchpoint(addr); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS)); LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x09); } } @@ -2857,8 +2776,8 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_continue_process || + (m_continue_process->GetID() == LLDB_INVALID_PROCESS_ID)) { LLDB_LOGF( log, "GDBRemoteCommunicationServerLLGS::%s failed, no process available", @@ -2876,7 +2795,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // Double check that we have such a thread. // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. - NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); + NativeThreadProtocol *thread = m_continue_process->GetThreadByID(tid); if (!thread) return SendErrorResponse(0x33); @@ -2889,12 +2808,12 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // All other threads stop while we're single stepping a thread. actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - Status error = m_debugged_process_up->Resume(actions); + Status error = m_continue_process->Resume(actions); if (error.Fail()) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", - __FUNCTION__, m_debugged_process_up->GetID(), tid, + __FUNCTION__, m_continue_process->GetID(), tid, error.AsCString()); return SendErrorResponse(0x49); } @@ -2906,7 +2825,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> GDBRemoteCommunicationServerLLGS::BuildTargetXml() { // Ensure we have a thread. - NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); + NativeThreadProtocol *thread = m_current_process->GetThreadAtIndex(0); if (!thread) return llvm::createStringError(llvm::inconvertibleErrorCode(), "No thread available"); @@ -2921,7 +2840,7 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { response.Printf("<target version=\"1.0\">"); response.Printf("<architecture>%s</architecture>", - m_debugged_process_up->GetArchitecture() + m_current_process->GetArchitecture() .GetTriple() .getArchName() .str() @@ -3010,22 +2929,22 @@ llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> GDBRemoteCommunicationServerLLGS::ReadXferObject(llvm::StringRef object, llvm::StringRef annex) { // Make sure we have a valid process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "No process available"); } if (object == "auxv") { // Grab the auxv data. - auto buffer_or_error = m_debugged_process_up->GetAuxvData(); + auto buffer_or_error = m_current_process->GetAuxvData(); if (!buffer_or_error) return llvm::errorCodeToError(buffer_or_error.getError()); return std::move(*buffer_or_error); } if (object == "libraries-svr4") { - auto library_list = m_debugged_process_up->GetLoadedSVR4Libraries(); + auto library_list = m_current_process->GetLoadedSVR4Libraries(); if (!library_list) return library_list.takeError(); @@ -3148,7 +3067,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( Status error = reg_context.ReadAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to save all register values: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x75); } @@ -3211,7 +3130,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( if (it == m_saved_registers_map.end()) { LLDB_LOG(log, "pid {0} does not have a register set save buffer for id {1}", - m_debugged_process_up->GetID(), save_id); + m_current_process->GetID(), save_id); return SendErrorResponse(0x77); } register_data_sp = it->second; @@ -3223,7 +3142,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( Status error = reg_context.WriteAllRegisterValues(register_data_sp); if (error.Fail()) { LLDB_LOG(log, "pid {0} failed to restore all register values: {1}", - m_debugged_process_up->GetID(), error); + m_current_process->GetID(), error); return SendErrorResponse(0x77); } @@ -3263,7 +3182,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach( } // Notify we attached by sending a stop packet. - return SendStopReasonForState(m_debugged_process_up->GetState()); + return SendStopReasonForState(m_current_process->GetState()); } GDBRemoteCommunication::PacketResult @@ -3293,7 +3212,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachWait( } // Notify we attached by sending a stop packet. - return SendStopReasonForState(m_debugged_process_up->GetState()); + return SendStopReasonForState(m_current_process->GetState()); } GDBRemoteCommunication::PacketResult @@ -3329,25 +3248,13 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait( } // Notify we attached by sending a stop packet. - return SendStopReasonForState(m_debugged_process_up->GetState()); + return SendStopReasonForState(m_current_process->GetState()); } GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); - StopSTDIOForwarding(); - // Fail if we don't have a current process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) { - LLDB_LOGF( - log, - "GDBRemoteCommunicationServerLLGS::%s failed, no process available", - __FUNCTION__); - return SendErrorResponse(0x15); - } - lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; // Consume the ';' after D. @@ -3362,19 +3269,32 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { return SendIllFormedResponse(packet, "D failed to parse the process id"); } - if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_up->GetID() != pid) { - return SendIllFormedResponse(packet, "Invalid pid"); - } - - const Status error = m_debugged_process_up->Detach(); - if (error.Fail()) { - LLDB_LOGF(log, - "GDBRemoteCommunicationServerLLGS::%s failed to detach from " - "pid %" PRIu64 ": %s\n", - __FUNCTION__, m_debugged_process_up->GetID(), error.AsCString()); - return SendErrorResponse(0x01); + // Detach forked children if their PID was specified *or* no PID was requested + // (i.e. detach-all packet). + llvm::Error detach_error = llvm::Error::success(); + bool detached = false; + for (auto it = m_debugged_processes.begin(); + it != m_debugged_processes.end();) { + if (pid == LLDB_INVALID_PROCESS_ID || pid == it->first) { + if (llvm::Error e = it->second->Detach().ToError()) + detach_error = llvm::joinErrors(std::move(detach_error), std::move(e)); + else { + if (it->second.get() == m_current_process) + m_current_process = nullptr; + if (it->second.get() == m_continue_process) + m_continue_process = nullptr; + it = m_debugged_processes.erase(it); + detached = true; + continue; + } + } + ++it; } + if (detach_error) + return SendErrorResponse(std::move(detach_error)); + if (!detached) + return SendErrorResponse(Status("PID %" PRIu64 " not traced", pid)); return SendOKResponse(); } @@ -3384,7 +3304,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); packet.SetFilePos(strlen("qThreadStopInfo")); - const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID); + const lldb::tid_t tid = packet.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID); if (tid == LLDB_INVALID_THREAD_ID) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s failed, could not " @@ -3401,19 +3321,19 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); // Ensure we have a debugged process. - if (!m_debugged_process_up || - (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) return SendErrorResponse(50); - LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID()); + LLDB_LOG(log, "preparing packet for pid {0}", m_current_process->GetID()); StreamString response; const bool threads_with_valid_stop_info_only = false; - llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo( - *m_debugged_process_up, threads_with_valid_stop_info_only); + llvm::Expected<json::Value> threads_info = + GetJSONThreadsInfo(*m_current_process, threads_with_valid_stop_info_only); if (!threads_info) { LLDB_LOG_ERROR(log, threads_info.takeError(), "failed to prepare a packet for pid {1}: {0}", - m_debugged_process_up->GetID()); + m_current_process->GetID()); return SendErrorResponse(52); } @@ -3427,8 +3347,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_current_process || + m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(68); packet.SetFilePos(strlen("qWatchpointSupportInfo")); @@ -3437,7 +3357,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( if (packet.GetChar() != ':') return SendErrorResponse(67); - auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo(); + auto hw_debug_cap = m_current_process->GetHardwareDebugSupportInfo(); StreamGDBRemote response; if (hw_debug_cap == llvm::None) @@ -3452,8 +3372,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( StringExtractorGDBRemote &packet) { // Fail if we don't have a current process. - if (!m_debugged_process_up || - m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_current_process || + m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(67); packet.SetFilePos(strlen("qFileLoadAddress:")); @@ -3465,7 +3385,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS; Status error = - m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address); + m_current_process->GetFileLoadAddress(file_name, file_load_address); if (error.Fail()) return SendErrorResponse(69); @@ -3501,16 +3421,169 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( } // Fail if we don't have a current process. - if (!m_debugged_process_up) + if (!m_current_process) return SendErrorResponse(68); - Status error = m_debugged_process_up->IgnoreSignals(signals); + Status error = m_current_process->IgnoreSignals(signals); if (error.Fail()) return SendErrorResponse(69); return SendOKResponse(); } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_qMemTags( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Ensure we have a process. + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(1); + } + + // We are expecting + // qMemTags:<hex address>,<hex length>:<hex type> + + // Address + packet.SetFilePos(strlen("qMemTags:")); + const char *current_char = packet.Peek(); + if (!current_char || *current_char == ',') + return SendIllFormedResponse(packet, "Missing address in qMemTags packet"); + const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); + + // Length + char previous_char = packet.GetChar(); + current_char = packet.Peek(); + // If we don't have a separator or the length field is empty + if (previous_char != ',' || (current_char && *current_char == ':')) + return SendIllFormedResponse(packet, + "Invalid addr,length pair in qMemTags packet"); + + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse( + packet, "Too short qMemtags: packet (looking for length)"); + const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); + + // Type + const char *invalid_type_err = "Invalid type field in qMemTags: packet"; + if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') + return SendIllFormedResponse(packet, invalid_type_err); + + int32_t type = + packet.GetS32(std::numeric_limits<int32_t>::max(), /*base=*/16); + if (type == std::numeric_limits<int32_t>::max() || + // To catch inputs like "123aardvark" that will parse but clearly aren't + // valid in this case. + packet.GetBytesLeft()) { + return SendIllFormedResponse(packet, invalid_type_err); + } + + StreamGDBRemote response; + std::vector<uint8_t> tags; + Status error = m_current_process->ReadMemoryTags(type, addr, length, tags); + if (error.Fail()) + return SendErrorResponse(1); + + // This m is here in case we want to support multi part replies in the future. + // In the same manner as qfThreadInfo/qsThreadInfo. + response.PutChar('m'); + response.PutBytesAsRawHex8(tags.data(), tags.size()); + return SendPacketNoLock(response.GetString()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_QMemTags( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + + // Ensure we have a process. + if (!m_current_process || + (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID)) { + LLDB_LOGF( + log, + "GDBRemoteCommunicationServerLLGS::%s failed, no process available", + __FUNCTION__); + return SendErrorResponse(1); + } + + // We are expecting + // QMemTags:<hex address>,<hex length>:<hex type>:<tags as hex bytes> + + // Address + packet.SetFilePos(strlen("QMemTags:")); + const char *current_char = packet.Peek(); + if (!current_char || *current_char == ',') + return SendIllFormedResponse(packet, "Missing address in QMemTags packet"); + const lldb::addr_t addr = packet.GetHexMaxU64(/*little_endian=*/false, 0); + + // Length + char previous_char = packet.GetChar(); + current_char = packet.Peek(); + // If we don't have a separator or the length field is empty + if (previous_char != ',' || (current_char && *current_char == ':')) + return SendIllFormedResponse(packet, + "Invalid addr,length pair in QMemTags packet"); + + if (packet.GetBytesLeft() < 1) + return SendIllFormedResponse( + packet, "Too short QMemtags: packet (looking for length)"); + const size_t length = packet.GetHexMaxU64(/*little_endian=*/false, 0); + + // Type + const char *invalid_type_err = "Invalid type field in QMemTags: packet"; + if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') + return SendIllFormedResponse(packet, invalid_type_err); + + // Our GetU64 uses strtoull which allows leading +/-, we don't want that. + const char *first_type_char = packet.Peek(); + if (first_type_char && (*first_type_char == '+' || *first_type_char == '-')) + return SendIllFormedResponse(packet, invalid_type_err); + + // The type is a signed integer but is in the packet as its raw bytes. + // So parse first as unsigned then cast to signed later. + // We extract to 64 bit, even though we only expect 32, so that we've + // got some invalid value we can check for. + uint64_t raw_type = + packet.GetU64(std::numeric_limits<uint64_t>::max(), /*base=*/16); + if (raw_type > std::numeric_limits<uint32_t>::max()) + return SendIllFormedResponse(packet, invalid_type_err); + int32_t type = static_cast<int32_t>(raw_type); + + // Tag data + if (packet.GetBytesLeft() < 1 || packet.GetChar() != ':') + return SendIllFormedResponse(packet, + "Missing tag data in QMemTags: packet"); + + // Must be 2 chars per byte + const char *invalid_data_err = "Invalid tag data in QMemTags: packet"; + if (packet.GetBytesLeft() % 2) + return SendIllFormedResponse(packet, invalid_data_err); + + // This is bytes here and is unpacked into target specific tags later + // We cannot assume that number of bytes == length here because the server + // can repeat tags to fill a given range. + std::vector<uint8_t> tag_data; + // Zero length writes will not have any tag data + // (but we pass them on because it will still check that tagging is enabled) + if (packet.GetBytesLeft()) { + size_t byte_count = packet.GetBytesLeft() / 2; + tag_data.resize(byte_count); + size_t converted_bytes = packet.GetHexBytes(tag_data, 0); + if (converted_bytes != byte_count) { + return SendIllFormedResponse(packet, invalid_data_err); + } + } + + Status status = + m_current_process->WriteMemoryTags(type, addr, length, tag_data); + return status.Success() ? SendOKResponse() : SendErrorResponse(1); +} + void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -3539,8 +3612,8 @@ void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( StringExtractorGDBRemote &packet) { // We have no thread if we don't have a process. - if (!m_debugged_process_up || - m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID) + if (!m_current_process || + m_current_process->GetID() == LLDB_INVALID_PROCESS_ID) return nullptr; // If the client hasn't asked for thread suffix support, there will not be a @@ -3551,9 +3624,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( return nullptr; else if (current_tid == 0) { // Pick a thread. - return m_debugged_process_up->GetThreadAtIndex(0); + return m_current_process->GetThreadAtIndex(0); } else - return m_debugged_process_up->GetThreadByID(current_tid); + return m_current_process->GetThreadByID(current_tid); } Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); @@ -3583,7 +3656,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); if (tid != 0) - return m_debugged_process_up->GetThreadByID(tid); + return m_current_process->GetThreadByID(tid); return nullptr; } @@ -3593,9 +3666,9 @@ lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { // Use whatever the debug process says is the current thread id since the // protocol either didn't specify or specified we want any/all threads // marked as the current thread. - if (!m_debugged_process_up) + if (!m_current_process) return LLDB_INVALID_THREAD_ID; - return m_debugged_process_up->GetCurrentThreadID(); + return m_current_process->GetCurrentThreadID(); } // Use the specific current thread id set by the gdb remote protocol. return m_current_tid; @@ -3616,9 +3689,9 @@ void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { FileSpec GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, const ArchSpec &arch) { - if (m_debugged_process_up) { + if (m_current_process) { FileSpec file_spec; - if (m_debugged_process_up + if (m_current_process ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) .Success()) { if (FileSystem::Instance().Exists(file_spec)) @@ -3653,3 +3726,93 @@ std::string GDBRemoteCommunicationServerLLGS::XMLEncodeAttributeValue( } return result; } + +llvm::Expected<lldb::tid_t> GDBRemoteCommunicationServerLLGS::ReadTid( + StringExtractorGDBRemote &packet, bool allow_all, lldb::pid_t default_pid) { + assert(m_current_process); + assert(m_current_process->GetID() != LLDB_INVALID_PROCESS_ID); + + auto pid_tid = packet.GetPidTid(default_pid); + if (!pid_tid) + return llvm::make_error<StringError>(inconvertibleErrorCode(), + "Malformed thread-id"); + + lldb::pid_t pid = pid_tid->first; + lldb::tid_t tid = pid_tid->second; + + if (!allow_all && pid == StringExtractorGDBRemote::AllProcesses) + return llvm::make_error<StringError>( + inconvertibleErrorCode(), + llvm::formatv("PID value {0} not allowed", pid == 0 ? 0 : -1)); + + if (!allow_all && tid == StringExtractorGDBRemote::AllThreads) + return llvm::make_error<StringError>( + inconvertibleErrorCode(), + llvm::formatv("TID value {0} not allowed", tid == 0 ? 0 : -1)); + + if (pid != StringExtractorGDBRemote::AllProcesses) { + if (pid != m_current_process->GetID()) + return llvm::make_error<StringError>( + inconvertibleErrorCode(), llvm::formatv("PID {0} not debugged", pid)); + } + + return tid; +} + +std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( + const llvm::ArrayRef<llvm::StringRef> client_features) { + std::vector<std::string> ret = + GDBRemoteCommunicationServerCommon::HandleFeatures(client_features); + ret.insert(ret.end(), { + "QThreadSuffixSupported+", + "QListThreadsInStopReply+", + "qXfer:features:read+", + }); + + // report server-only features + using Extension = NativeProcessProtocol::Extension; + Extension plugin_features = m_process_factory.GetSupportedExtensions(); + if (bool(plugin_features & Extension::pass_signals)) + ret.push_back("QPassSignals+"); + if (bool(plugin_features & Extension::auxv)) + ret.push_back("qXfer:auxv:read+"); + if (bool(plugin_features & Extension::libraries_svr4)) + ret.push_back("qXfer:libraries-svr4:read+"); + if (bool(plugin_features & Extension::memory_tagging)) + ret.push_back("memory-tagging+"); + + // check for client features + m_extensions_supported = {}; + for (llvm::StringRef x : client_features) + m_extensions_supported |= + llvm::StringSwitch<Extension>(x) + .Case("multiprocess+", Extension::multiprocess) + .Case("fork-events+", Extension::fork) + .Case("vfork-events+", Extension::vfork) + .Default({}); + + m_extensions_supported &= plugin_features; + + // fork & vfork require multiprocess + if (!bool(m_extensions_supported & Extension::multiprocess)) + m_extensions_supported &= ~(Extension::fork | Extension::vfork); + + // report only if actually supported + if (bool(m_extensions_supported & Extension::multiprocess)) + ret.push_back("multiprocess+"); + if (bool(m_extensions_supported & Extension::fork)) + ret.push_back("fork-events+"); + if (bool(m_extensions_supported & Extension::vfork)) + ret.push_back("vfork-events+"); + + for (auto &x : m_debugged_processes) + SetEnabledExtensions(*x.second); + return ret; +} + +void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions( + NativeProcessProtocol &process) { + NativeProcessProtocol::Extension flags = m_extensions_supported; + assert(!bool(flags & ~m_process_factory.GetSupportedExtensions())); + process.SetEnabledExtensions(flags); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index c51139924559..04d0605fe420 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -78,6 +78,10 @@ public: void DidExec(NativeProcessProtocol *process) override; + void + NewSubprocess(NativeProcessProtocol *parent_process, + std::unique_ptr<NativeProcessProtocol> child_process) override; + Status InitializeConnection(std::unique_ptr<Connection> connection); protected: @@ -86,8 +90,11 @@ protected: const NativeProcessProtocol::Factory &m_process_factory; lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID; lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID; + NativeProcessProtocol *m_current_process; + NativeProcessProtocol *m_continue_process; std::recursive_mutex m_debugged_process_mutex; - std::unique_ptr<NativeProcessProtocol> m_debugged_process_up; + std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>> + m_debugged_processes; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; @@ -98,6 +105,10 @@ protected: std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; uint32_t m_next_saved_registers_id = 1; bool m_handshake_completed = false; + bool m_thread_suffix_supported = false; + bool m_list_threads_in_stop_reply = false; + + NativeProcessProtocol::Extension m_extensions_supported = {}; PacketResult SendONotification(const char *buffer, uint32_t len); @@ -119,6 +130,10 @@ protected: PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet); + PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet); + + PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet); + PacketResult Handle_C(StringExtractorGDBRemote &packet); PacketResult Handle_c(StringExtractorGDBRemote &packet); @@ -167,15 +182,15 @@ protected: PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); - PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceSupported(StringExtractorGDBRemote &packet); - PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceStart(StringExtractorGDBRemote &packet); - PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceStop(StringExtractorGDBRemote &packet); - PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceGetState(StringExtractorGDBRemote &packet); - PacketResult Handle_jLLDBTraceSupportedType(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceGetBinaryData(StringExtractorGDBRemote &packet); PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); @@ -201,6 +216,10 @@ protected: PacketResult Handle_g(StringExtractorGDBRemote &packet); + PacketResult Handle_qMemTags(StringExtractorGDBRemote &packet); + + PacketResult Handle_QMemTags(StringExtractorGDBRemote &packet); + void SetCurrentThreadID(lldb::tid_t tid); lldb::tid_t GetCurrentThreadID() const; @@ -219,6 +238,9 @@ protected: static std::string XMLEncodeAttributeValue(llvm::StringRef value); + virtual std::vector<std::string> HandleFeatures( + const llvm::ArrayRef<llvm::StringRef> client_features) override; + private: llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> BuildTargetXml(); @@ -244,6 +266,18 @@ private: void StopSTDIOForwarding(); + // Read thread-id from packet. If the thread-id is correct, returns it. + // Otherwise, returns the error. + // + // If allow_all is true, then the pid/tid value of -1 ('all') will be allowed. + // In any case, the function assumes that exactly one inferior is being + // debugged and rejects pid values that do no match that inferior. + llvm::Expected<lldb::tid_t> ReadTid(StringExtractorGDBRemote &packet, + bool allow_all, lldb::pid_t default_pid); + + // Call SetEnabledExtensions() with appropriate flags on the process. + void SetEnabledExtensions(NativeProcessProtocol &process); + // For GDBRemoteCommunicationServerLLGS only GDBRemoteCommunicationServerLLGS(const GDBRemoteCommunicationServerLLGS &) = delete; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 3462fb7ec8b9..7c2f80dc76b8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -8,7 +8,7 @@ #include "GDBRemoteCommunicationServerPlatform.h" -#include <errno.h> +#include <cerrno> #include <chrono> #include <csignal> @@ -153,7 +153,8 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform( } // Destructor -GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {} +GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() = + default; Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer( const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid, diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 10006616b0c6..65cf9fb2a834 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -36,7 +36,7 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext( : RegisterContext(thread, concrete_frame_idx), m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once), - m_write_all_at_once(write_all_at_once) { + m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) { // Resize our vector of bools to contain one bool for every register. We will // use these boolean values to know when a register value is valid in // m_reg_data. @@ -50,13 +50,14 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext( } // Destructor -GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {} +GDBRemoteRegisterContext::~GDBRemoteRegisterContext() = default; void GDBRemoteRegisterContext::InvalidateAllRegisters() { SetAllRegisterValid(false); } void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) { + m_gpacket_cached = b; std::vector<bool>::iterator pos, end = m_reg_valid.end(); for (pos = m_reg_valid.begin(); pos != end; ++pos) *pos = b; @@ -200,7 +201,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; if (!GetRegisterIsValid(reg)) { - if (m_read_all_at_once) { + if (m_read_all_at_once && !m_gpacket_cached) { if (DataBufferSP buffer_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) { memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()), @@ -221,7 +222,10 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, m_reg_valid[i] = false; } } - return true; + + m_gpacket_cached = true; + if (GetRegisterIsValid(reg)) + return true; } else { Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD | GDBR_LOG_PACKETS)); @@ -233,9 +237,9 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, " bytes " "but only got %" PRId64 " bytes.", m_reg_data.GetByteSize(), buffer_sp->GetByteSize()); + return false; } } - return false; } if (reg_info->value_regs) { // Process this composite register request by delegating to the @@ -249,7 +253,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info, break; // We have a valid primordial register as our constituent. Grab the // corresponding register info. - const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg); + const RegisterInfo *prim_reg_info = + GetRegisterInfo(eRegisterKindProcessPlugin, prim_reg); if (prim_reg_info == nullptr) success = false; else { @@ -359,7 +364,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, reg_info->byte_size, // dst length m_reg_data.GetByteOrder())) // dst byte order { - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { if (m_write_all_at_once) { // Invalidate all register values @@ -395,7 +400,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, break; // We have a valid primordial register as our constituent. Grab the // corresponding register info. - const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg); + const RegisterInfo *value_reg_info = + GetRegisterInfo(eRegisterKindProcessPlugin, reg); if (value_reg_info == nullptr) success = false; else @@ -414,9 +420,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info, if (reg_info->invalidate_regs) { for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0]; reg != LLDB_INVALID_REGNUM; - reg = reg_info->invalidate_regs[++idx]) { - SetRegisterIsValid(reg, false); - } + reg = reg_info->invalidate_regs[++idx]) + SetRegisterIsValid(ConvertRegisterKindToRegisterNumber( + eRegisterKindProcessPlugin, reg), + false); } return success; @@ -501,7 +508,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues( const bool use_g_packet = !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process); - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { if (gdb_comm.SyncThreadState(m_thread.GetProtocolID())) InvalidateAllRegisters(); @@ -567,7 +574,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues( const bool use_g_packet = !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process); - GDBRemoteClientBase::Lock lock(gdb_comm, false); + GDBRemoteClientBase::Lock lock(gdb_comm); if (lock) { // The data_sp contains the G response packet. if (use_g_packet) { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 252d7b359ee8..18fcb73b9815 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -118,6 +118,7 @@ protected: DataExtractor m_reg_data; bool m_read_all_at_once; bool m_write_all_at_once; + bool m_gpacket_cached; private: // Helper function for ReadRegisterBytes(). diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 1214812b60b0..b8a737586eb4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -8,8 +8,8 @@ #include "lldb/Host/Config.h" -#include <errno.h> -#include <stdlib.h> +#include <cerrno> +#include <cstdlib> #if LLDB_ENABLE_POSIX #include <netinet/in.h> #include <sys/mman.h> @@ -20,8 +20,8 @@ #if defined(__APPLE__) #include <sys/sysctl.h> #endif +#include <ctime> #include <sys/types.h> -#include <time.h> #include <algorithm> #include <csignal> @@ -137,7 +137,7 @@ public: m_collection_sp->Initialize(g_processgdbremote_properties); } - ~PluginProperties() override {} + ~PluginProperties() override = default; uint64_t GetPacketTimeout() { const uint32_t idx = ePropertyPacketTimeout; @@ -215,6 +215,10 @@ ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, return process_sp; } +std::chrono::seconds ProcessGDBRemote::GetPacketTimeout() { + return std::chrono::seconds(GetGlobalPluginProperties()->GetPacketTimeout()); +} + bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) { if (plugin_specified_by_name) @@ -463,7 +467,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { assert(packet_len < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response) == GDBRemoteCommunication::PacketResult::Success) { response_type = response.GetResponseType(); if (response_type == StringExtractorGDBRemote::eResponse) { @@ -1013,7 +1017,7 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) { for (size_t idx = 0; idx < num_cmds; idx++) { StringExtractorGDBRemote response; m_gdb_comm.SendPacketAndWaitForResponse( - GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false); + GetExtraStartupCommands().GetArgumentAtIndex(idx), response); } return error; } @@ -1040,6 +1044,12 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { process_arch.GetTriple().getTriple()); } + if (int addresssable_bits = m_gdb_comm.GetAddressingBits()) { + lldb::addr_t address_mask = ~((1ULL << addresssable_bits) - 1); + SetCodeAddressMask(address_mask); + SetDataAddressMask(address_mask); + } + if (process_arch.IsValid()) { const ArchSpec &target_arch = GetTarget().GetArchitecture(); if (target_arch.IsValid()) { @@ -1201,34 +1211,26 @@ Status ProcessGDBRemote::DoAttachToProcessWithName( return error; } -lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options, - Status &error) { - return m_gdb_comm.SendStartTracePacket(options, error); -} - -Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) { - return m_gdb_comm.SendStopTracePacket(uid, thread_id); +llvm::Expected<TraceSupportedResponse> ProcessGDBRemote::TraceSupported() { + return m_gdb_comm.SendTraceSupported(GetInterruptTimeout()); } -Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { - return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset); +llvm::Error ProcessGDBRemote::TraceStop(const TraceStopRequest &request) { + return m_gdb_comm.SendTraceStop(request, GetInterruptTimeout()); } -Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset) { - return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset); +llvm::Error ProcessGDBRemote::TraceStart(const llvm::json::Value &request) { + return m_gdb_comm.SendTraceStart(request, GetInterruptTimeout()); } -Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid, - TraceOptions &options) { - return m_gdb_comm.SendGetTraceConfigPacket(uid, options); +llvm::Expected<std::string> +ProcessGDBRemote::TraceGetState(llvm::StringRef type) { + return m_gdb_comm.SendTraceGetState(type, GetInterruptTimeout()); } -llvm::Expected<TraceTypeInfo> ProcessGDBRemote::GetSupportedTraceType() { - return m_gdb_comm.SendGetSupportedTraceType(); +llvm::Expected<std::vector<uint8_t>> +ProcessGDBRemote::TraceGetBinaryData(const TraceGetBinaryDataRequest &request) { + return m_gdb_comm.SendTraceGetBinaryData(request, GetInterruptTimeout()); } void ProcessGDBRemote::DidExit() { @@ -1473,7 +1475,7 @@ void ProcessGDBRemote::HandleStopReplySequence() { while (true) { // Send vStopped StringExtractorGDBRemote response; - m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false); + m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response); // OK represents end of signal list if (response.IsOKResponse()) @@ -1493,22 +1495,22 @@ void ProcessGDBRemote::ClearThreadIDList() { m_thread_pcs.clear(); } -size_t -ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) { +size_t ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue( + llvm::StringRef value) { m_thread_ids.clear(); - size_t comma_pos; - lldb::tid_t tid; - while ((comma_pos = value.find(',')) != std::string::npos) { - value[comma_pos] = '\0'; - // thread in big endian hex - tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); - if (tid != LLDB_INVALID_THREAD_ID) - m_thread_ids.push_back(tid); - value.erase(0, comma_pos + 1); - } - tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16); - if (tid != LLDB_INVALID_THREAD_ID) - m_thread_ids.push_back(tid); + lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); + StringExtractorGDBRemote thread_ids{value}; + + do { + auto pid_tid = thread_ids.GetPidTid(pid); + if (pid_tid && pid_tid->first == pid) { + lldb::tid_t tid = pid_tid->second; + if (tid != LLDB_INVALID_THREAD_ID && + tid != StringExtractorGDBRemote::AllProcesses) + m_thread_ids.push_back(tid); + } + } while (thread_ids.GetChar() == ','); + return m_thread_ids.size(); } @@ -1525,7 +1527,7 @@ ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) { value.erase(0, comma_pos + 1); } pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16); - if (pc != LLDB_INVALID_THREAD_ID) + if (pc != LLDB_INVALID_ADDRESS) m_thread_pcs.push_back(pc); return m_thread_pcs.size(); } @@ -1750,7 +1752,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( if (thread_sp) { ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread_sp.get()); - gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true); + RegisterContextSP gdb_reg_ctx_sp(gdb_thread->GetRegisterContext()); + + gdb_reg_ctx_sp->InvalidateIfNeeded(true); auto iter = std::find(m_thread_ids.begin(), m_thread_ids.end(), tid); if (iter != m_thread_ids.end()) { @@ -1762,7 +1766,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( DataBufferSP buffer_sp(new DataBufferHeap( reg_value_extractor.GetStringRef().size() / 2, 0)); reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc'); - gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); + uint32_t lldb_regnum = + gdb_reg_ctx_sp->ConvertRegisterKindToRegisterNumber( + eRegisterKindProcessPlugin, pair.first); + gdb_thread->PrivateSetRegisterValue(lldb_regnum, buffer_sp->GetData()); } // AArch64 SVE specific code below calls AArch64SVEReconfigure to update @@ -1827,8 +1834,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // If the current pc is a breakpoint site then the StopInfo // should be set to Breakpoint Otherwise, it will be set to // Trace. - if (bp_site_sp && - bp_site_sp->ValidForThisThread(thread_sp.get())) { + if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); @@ -1848,7 +1854,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // breakpoint here, that will be taken care of when the thread // resumes and notices that there's a breakpoint under the pc. handled = true; - if (bp_site_sp->ValidForThisThread(thread_sp.get())) { + if (bp_site_sp->ValidForThisThread(*thread_sp)) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); @@ -1899,6 +1905,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithExec(*thread_sp)); handled = true; + } else if (reason == "processor trace") { + thread_sp->SetStopInfo(StopInfo::CreateStopReasonProcessorTrace( + *thread_sp, description.c_str())); } } else if (!signo) { addr_t pc = thread_sp->GetRegisterContext()->GetPC(); @@ -1911,7 +1920,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // as such. This can happen when the thread is involuntarily // interrupted (e.g. due to stops on other threads) just as it is // about to execute the breakpoint instruction. - if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) { + if (bp_site_sp && bp_site_sp->ValidForThisThread(*thread_sp)) { thread_sp->SetStopInfo( StopInfo::CreateStopReasonWithBreakpointSiteID( *thread_sp, bp_site_sp->GetID())); @@ -1936,7 +1945,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo( // reason. We don't need to worry about stepping over the // breakpoint here, that will be taken care of when the thread // resumes and notices that there's a breakpoint under the pc. - if (bp_site_sp->ValidForThisThread(thread_sp.get())) { + if (bp_site_sp->ValidForThisThread(*thread_sp)) { if (m_breakpoint_pc_offset != 0) thread_sp->GetRegisterContext()->SetPC(pc); thread_sp->SetStopInfo( @@ -2139,6 +2148,7 @@ ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) { } StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { + lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); stop_packet.SetFilePos(0); const char stop_type = stop_packet.GetChar(); switch (stop_type) { @@ -2153,14 +2163,12 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { if (stop_id == 0) { // Our first stop, make sure we have a process ID, and also make sure we // know about our registers - if (GetID() == LLDB_INVALID_PROCESS_ID) { - lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) - SetID(pid); - } + if (GetID() == LLDB_INVALID_PROCESS_ID && pid != LLDB_INVALID_PROCESS_ID) + SetID(pid); BuildDynamicRegisterInfo(true); } // Stop with signal and thread info + lldb::pid_t stop_pid = LLDB_INVALID_PROCESS_ID; lldb::tid_t tid = LLDB_INVALID_THREAD_ID; const uint8_t signo = stop_packet.GetHexU8(); llvm::StringRef key; @@ -2189,24 +2197,18 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { value.getAsInteger(16, x); exc_data.push_back(x); } else if (key.compare("thread") == 0) { - // thread in big endian hex - if (value.getAsInteger(16, tid)) + // thread-id + StringExtractorGDBRemote thread_id{value}; + auto pid_tid = thread_id.GetPidTid(pid); + if (pid_tid) { + stop_pid = pid_tid->first; + tid = pid_tid->second; + } else tid = LLDB_INVALID_THREAD_ID; } else if (key.compare("threads") == 0) { std::lock_guard<std::recursive_mutex> guard( m_thread_list_real.GetMutex()); - - m_thread_ids.clear(); - // A comma separated list of all threads in the current - // process that includes the thread for this stop reply packet - lldb::tid_t tid; - while (!value.empty()) { - llvm::StringRef tid_str; - std::tie(tid_str, value) = value.split(','); - if (tid_str.getAsInteger(16, tid)) - tid = LLDB_INVALID_THREAD_ID; - m_thread_ids.push_back(tid); - } + UpdateThreadIDsFromStopReplyThreadsValue(value); } else if (key.compare("thread-pcs") == 0) { m_thread_pcs.clear(); // A comma separated list of all threads in the current @@ -2319,6 +2321,14 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) { } } + if (stop_pid != LLDB_INVALID_PROCESS_ID && stop_pid != pid) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + LLDB_LOG(log, + "Received stop for incorrect PID = {0} (inferior PID = {1})", + stop_pid, pid); + return eStateInvalid; + } + if (tid == LLDB_INVALID_THREAD_ID) { // A thread id may be invalid if the response is old style 'S' packet // which does not provide the @@ -2406,7 +2416,7 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) { // file handle and debugserver will go away, and we can be done... m_gdb_comm.Disconnect(); } else - caused_stop = m_gdb_comm.Interrupt(); + caused_stop = m_gdb_comm.Interrupt(GetInterruptTimeout()); return error; } @@ -2557,11 +2567,11 @@ Status ProcessGDBRemote::DoDestroy() { if (m_gdb_comm.IsConnected()) { if (m_public_state.GetValue() != eStateAttaching) { StringExtractorGDBRemote response; - bool send_async = true; GDBRemoteCommunication::ScopedTimeout(m_gdb_comm, std::chrono::seconds(3)); - if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) == + if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { char packet_cmd = response.GetChar(0); @@ -2725,7 +2735,8 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, assert(packet_len + 1 < (int)sizeof(packet)); UNUSED_IF_ASSERT_DISABLED(packet_len); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsNormalResponse()) { error.Clear(); @@ -2761,6 +2772,37 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size, return 0; } +bool ProcessGDBRemote::SupportsMemoryTagging() { + return m_gdb_comm.GetMemoryTaggingSupported(); +} + +llvm::Expected<std::vector<uint8_t>> +ProcessGDBRemote::DoReadMemoryTags(lldb::addr_t addr, size_t len, + int32_t type) { + // By this point ReadMemoryTags has validated that tagging is enabled + // for this target/process/address. + DataBufferSP buffer_sp = m_gdb_comm.ReadMemoryTags(addr, len, type); + if (!buffer_sp) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Error reading memory tags from remote"); + } + + // Return the raw tag data + llvm::ArrayRef<uint8_t> tag_data = buffer_sp->GetData(); + std::vector<uint8_t> got; + got.reserve(tag_data.size()); + std::copy(tag_data.begin(), tag_data.end(), std::back_inserter(got)); + return got; +} + +Status ProcessGDBRemote::DoWriteMemoryTags(lldb::addr_t addr, size_t len, + int32_t type, + const std::vector<uint8_t> &tags) { + // By now WriteMemoryTags should have validated that tagging is enabled + // for this target/process. + return m_gdb_comm.WriteMemoryTags(addr, len, type, tags); +} + Status ProcessGDBRemote::WriteObjectFile( std::vector<ObjectFile::LoadableData> entries) { Status error; @@ -2851,7 +2893,7 @@ Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) { StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - true) == + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { m_erased_flash_ranges.Insert(range, true); @@ -2880,7 +2922,8 @@ Status ProcessGDBRemote::FlashDone() { if (m_erased_flash_ranges.IsEmpty()) return status; StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) == + if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { m_erased_flash_ranges.Clear(); @@ -2941,7 +2984,7 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf, } StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - true) == + GetInterruptTimeout()) == GDBRemoteCommunication::PacketResult::Success) { if (response.IsOKResponse()) { error.Clear(); @@ -3117,7 +3160,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { (!bp_site->HardwareRequired())) { // Try to send off a software breakpoint packet ($Z0) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( - eBreakpointSoftware, true, addr, bp_op_size); + eBreakpointSoftware, true, addr, bp_op_size, GetInterruptTimeout()); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3157,7 +3200,7 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) { if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Try to send off a hardware breakpoint packet ($Z1) uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket( - eBreakpointHardware, true, addr, bp_op_size); + eBreakpointHardware, true, addr, bp_op_size, GetInterruptTimeout()); if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3221,13 +3264,15 @@ Status ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) { case BreakpointSite::eHardware: if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, - addr, bp_op_size)) + addr, bp_op_size, + GetInterruptTimeout())) error.SetErrorToGenericError(); break; case BreakpointSite::eExternal: { if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, - addr, bp_op_size)) + addr, bp_op_size, + GetInterruptTimeout())) error.SetErrorToGenericError(); } break; } @@ -3283,7 +3328,8 @@ Status ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) { // Pass down an appropriate z/Z packet... if (m_gdb_comm.SupportsGDBStoppointPacket(type)) { if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, - wp->GetByteSize()) == 0) { + wp->GetByteSize(), + GetInterruptTimeout()) == 0) { wp->SetEnabled(true, notify); return error; } else @@ -3329,7 +3375,8 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) { GDBStoppointType type = GetGDBStoppointType(wp); // Pass down an appropriate z/Z packet... if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, - wp->GetByteSize()) == 0) { + wp->GetByteSize(), + GetInterruptTimeout()) == 0) { wp->SetEnabled(false, notify); return error; } else @@ -3354,7 +3401,7 @@ Status ProcessGDBRemote::DoSignal(int signo) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); LLDB_LOGF(log, "ProcessGDBRemote::DoSignal (signal = %d)", signo); - if (!m_gdb_comm.SendAsyncSignal(signo)) + if (!m_gdb_comm.SendAsyncSignal(signo, GetInterruptTimeout())) error.SetErrorStringWithFormat("failed to send signal %i", signo); return error; } @@ -3682,12 +3729,25 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { __FUNCTION__, arg, process->GetID()); EventSP event_sp; + + // We need to ignore any packets that come in after we have + // have decided the process has exited. There are some + // situations, for instance when we try to interrupt a running + // process and the interrupt fails, where another packet might + // get delivered after we've decided to give up on the process. + // But once we've decided we are done with the process we will + // not be in a state to do anything useful with new packets. + // So it is safer to simply ignore any remaining packets by + // explicitly checking for eStateExited before reentering the + // fetch loop. + bool done = false; - while (!done) { + while (!done && process->GetPrivateState() != eStateExited) { LLDB_LOGF(log, "ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); + if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) { @@ -3719,7 +3779,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { // send the vCont packet if (!process->GetGDBRemote().SendvContPacket( llvm::StringRef(continue_cstr, continue_cstr_len), - response)) { + process->GetInterruptTimeout(), response)) { // Something went wrong done = true; break; @@ -3731,6 +3791,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { process->GetGDBRemote().SendContinuePacketAndWaitForResponse( *process, *process->GetUnixSignals(), llvm::StringRef(continue_cstr, continue_cstr_len), + process->GetInterruptTimeout(), response); // We need to immediately clear the thread ID list so we are sure @@ -3786,6 +3847,7 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) { } else { process->SetExitStatus(-1, "lost connection"); } + done = true; break; } @@ -4024,8 +4086,7 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4097,8 +4158,7 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender( StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4131,8 +4191,7 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { StringExtractorGDBRemote response; response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) == + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4898,8 +4957,7 @@ Status ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file, packet.PutStringAsRawHex8(file_path); StringExtractorGDBRemote response; - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response, - false) != + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != GDBRemoteCommunication::PacketResult::Success) return Status("Sending qFileLoadAddress packet failed"); @@ -5135,7 +5193,7 @@ public: m_option_group.Finalize(); } - ~CommandObjectProcessGDBRemoteSpeedTest() override {} + ~CommandObjectProcessGDBRemoteSpeedTest() override = default; Options *GetOptions() override { return &m_option_group; } @@ -5186,7 +5244,7 @@ public: : CommandObjectParsed(interpreter, "process plugin packet history", "Dumps the packet history buffer. ", nullptr) {} - ~CommandObjectProcessGDBRemotePacketHistory() override {} + ~CommandObjectProcessGDBRemotePacketHistory() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5217,7 +5275,7 @@ public: "Maximum size that lldb will try to read/write one one chunk.", nullptr) {} - ~CommandObjectProcessGDBRemotePacketXferSize() override {} + ~CommandObjectProcessGDBRemotePacketXferSize() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5226,7 +5284,6 @@ public: "amount to be transferred when " "reading/writing", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -5259,7 +5316,7 @@ public: "stripped from the result.", nullptr) {} - ~CommandObjectProcessGDBRemotePacketSend() override {} + ~CommandObjectProcessGDBRemotePacketSend() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -5267,7 +5324,6 @@ public: result.AppendErrorWithFormat( "'%s' takes a one or more packet content arguments", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -5276,10 +5332,9 @@ public: if (process) { for (size_t i = 0; i < argc; ++i) { const char *packet_cstr = command.GetArgumentAtIndex(0); - bool send_async = true; StringExtractorGDBRemote response; process->GetGDBRemote().SendPacketAndWaitForResponse( - packet_cstr, response, send_async); + packet_cstr, response, process->GetInterruptTimeout()); result.SetStatus(eReturnStatusSuccessFinishResult); Stream &output_strm = result.GetOutputStream(); output_strm.Printf(" packet: %s\n", packet_cstr); @@ -5310,14 +5365,13 @@ public: "encoded into a valid 'qRcmd' packet, sent and the " "response will be printed.") {} - ~CommandObjectProcessGDBRemotePacketMonitor() override {} + ~CommandObjectProcessGDBRemotePacketMonitor() override = default; bool DoExecute(llvm::StringRef command, CommandReturnObject &result) override { if (command.empty()) { result.AppendErrorWithFormat("'%s' takes a command string argument", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } @@ -5328,11 +5382,10 @@ public: packet.PutCString("qRcmd,"); packet.PutBytesAsRawHex8(command.data(), command.size()); - bool send_async = true; StringExtractorGDBRemote response; Stream &output_strm = result.GetOutputStream(); process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport( - packet.GetString(), response, send_async, + packet.GetString(), response, process->GetInterruptTimeout(), [&output_strm](llvm::StringRef output) { output_strm << output; }); result.SetStatus(eReturnStatusSuccessFinishResult); output_strm.Printf(" packet: %s\n", packet.GetData()); @@ -5374,7 +5427,7 @@ public: interpreter))); } - ~CommandObjectProcessGDBRemotePacket() override {} + ~CommandObjectProcessGDBRemotePacket() override = default; }; class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { @@ -5389,7 +5442,7 @@ public: CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter))); } - ~CommandObjectMultiwordProcessGDBRemote() override {} + ~CommandObjectMultiwordProcessGDBRemote() override = default; }; CommandObject *ProcessGDBRemote::GetPluginCommandObject() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 0921bf17c4e4..fe04cdddd0f5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -68,6 +68,8 @@ public: static const char *GetPluginDescriptionStatic(); + static std::chrono::seconds GetPacketTimeout(); + // Check if a given Process bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; @@ -163,22 +165,16 @@ public: Status GetWatchpointSupportInfo(uint32_t &num) override; - lldb::user_id_t StartTrace(const TraceOptions &options, - Status &error) override; - - Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override; + llvm::Expected<TraceSupportedResponse> TraceSupported() override; - Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0) override; + llvm::Error TraceStop(const TraceStopRequest &request) override; - Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id, - llvm::MutableArrayRef<uint8_t> &buffer, - size_t offset = 0) override; + llvm::Error TraceStart(const llvm::json::Value &request) override; - llvm::Expected<TraceTypeInfo> GetSupportedTraceType() override; + llvm::Expected<std::string> TraceGetState(llvm::StringRef type) override; - Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override; + llvm::Expected<std::vector<uint8_t>> + TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override; Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override; @@ -239,6 +235,8 @@ protected: friend class GDBRemoteCommunicationClient; friend class GDBRemoteRegisterContext; + bool SupportsMemoryTagging() override; + /// Broadcaster event bits definitions. enum { eBroadcastBitAsyncContinue = (1 << 0), @@ -339,7 +337,7 @@ protected: size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value); - size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value); + size_t UpdateThreadIDsFromStopReplyThreadsValue(llvm::StringRef value); bool HandleNotifyPacket(StringExtractorGDBRemote &packet); @@ -410,6 +408,12 @@ protected: bool HasErased(FlashRange range); + llvm::Expected<std::vector<uint8_t>> + DoReadMemoryTags(lldb::addr_t addr, size_t len, int32_t type) override; + + Status DoWriteMemoryTags(lldb::addr_t addr, size_t len, int32_t type, + const std::vector<uint8_t> &tags) override; + private: // For ProcessGDBRemote only std::string m_partial_profile_data; diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index 05a48acc2f7a..385557422758 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -138,10 +138,10 @@ private: /// /// \param[in] module_sp The module to grab the .text section from. /// -/// \param[in/out] breakpad_uuid A vector that will receive the calculated +/// \param[in,out] breakpad_uuid A vector that will receive the calculated /// breakpad .text hash. /// -/// \param[in/out] facebook_uuid A vector that will receive the calculated +/// \param[in,out] facebook_uuid A vector that will receive the calculated /// facebook .text hash. /// void HashElfTextSection(ModuleSP module_sp, std::vector<uint8_t> &breakpad_uuid, @@ -548,7 +548,7 @@ void ProcessMinidump::ReadModuleList() { // check if the process is wow64 - a 32 bit windows process running on a // 64 bit windows - if (llvm::StringRef(name).endswith_lower("wow64.dll")) { + if (llvm::StringRef(name).endswith_insensitive("wow64.dll")) { m_is_wow64 = true; } @@ -871,7 +871,7 @@ public: m_option_group.Finalize(); } - ~CommandObjectProcessMinidumpDump() override {} + ~CommandObjectProcessMinidumpDump() override = default; Options *GetOptions() override { return &m_option_group; } @@ -880,7 +880,6 @@ public: if (argc > 0) { result.AppendErrorWithFormat("'%s' take no arguments, only options", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); return false; } SetDefaultOptionsIfNoneAreSet(); @@ -1001,7 +1000,7 @@ public: CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter))); } - ~CommandObjectMultiwordProcessMinidump() override {} + ~CommandObjectMultiwordProcessMinidump() override = default; }; CommandObject *ProcessMinidump::GetPluginCommandObject() { diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp index eb48785263fc..7e309e8322a8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp @@ -16,7 +16,7 @@ #include "lldb/lldb-enumerations.h" // C includes -#include <assert.h> +#include <cassert> // C++ includes diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp index c7809c5f19b6..e2b7c0e362a7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp @@ -14,7 +14,7 @@ #include "lldb/lldb-enumerations.h" // C includes -#include <assert.h> +#include <cassert> // C++ includes diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp index e146a1a1af92..1fbc52815238 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp @@ -38,7 +38,7 @@ ThreadMinidump::ThreadMinidump(Process &process, const minidump::Thread &td, : Thread(process, td.ThreadId), m_thread_reg_ctx_sp(), m_gpregset_data(gpregset_data) {} -ThreadMinidump::~ThreadMinidump() {} +ThreadMinidump::~ThreadMinidump() = default; void ThreadMinidump::RefreshStateAfterStop() {} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp new file mode 100644 index 000000000000..09e9375b6f66 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -0,0 +1,313 @@ +//===-- ScriptedProcess.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ScriptedProcess.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" + +#include "lldb/Host/OptionParser.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupBoolean.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/RegisterContext.h" + +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" +#include "lldb/Utility/State.h" + +#include <mutex> + +LLDB_PLUGIN_DEFINE(ScriptedProcess) + +using namespace lldb; +using namespace lldb_private; + +ConstString ScriptedProcess::GetPluginNameStatic() { + static ConstString g_name("ScriptedProcess"); + return g_name; +} + +const char *ScriptedProcess::GetPluginDescriptionStatic() { + return "Scripted Process plug-in."; +} + +static constexpr lldb::ScriptLanguage g_supported_script_languages[] = { + ScriptLanguage::eScriptLanguagePython, +}; + +bool ScriptedProcess::IsScriptLanguageSupported(lldb::ScriptLanguage language) { + llvm::ArrayRef<lldb::ScriptLanguage> supported_languages = + llvm::makeArrayRef(g_supported_script_languages); + + return llvm::is_contained(supported_languages, language); +} + +void ScriptedProcess::CheckInterpreterAndScriptObject() const { + lldbassert(m_interpreter && "Invalid Script Interpreter."); + lldbassert(m_script_object_sp && "Invalid Script Object."); +} + +lldb::ProcessSP ScriptedProcess::CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *file, + bool can_connect) { + if (!target_sp || + !IsScriptLanguageSupported(target_sp->GetDebugger().GetScriptLanguage())) + return nullptr; + + Status error; + ScriptedProcess::ScriptedProcessInfo scripted_process_info( + target_sp->GetProcessLaunchInfo()); + + auto process_sp = std::make_shared<ScriptedProcess>( + target_sp, listener_sp, scripted_process_info, error); + + if (error.Fail() || !process_sp || !process_sp->m_script_object_sp || + !process_sp->m_script_object_sp->IsValid()) { + LLDB_LOGF(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS), "%s", + error.AsCString()); + return nullptr; + } + + return process_sp; +} + +bool ScriptedProcess::CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) { + return true; +} + +ScriptedProcess::ScriptedProcess( + lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const ScriptedProcess::ScriptedProcessInfo &scripted_process_info, + Status &error) + : Process(target_sp, listener_sp), + m_scripted_process_info(scripted_process_info) { + + if (!target_sp) { + error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", + __FUNCTION__, "Invalid target"); + return; + } + + m_interpreter = target_sp->GetDebugger().GetScriptInterpreter(); + + if (!m_interpreter) { + error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", + __FUNCTION__, + "Debugger has no Script Interpreter"); + return; + } + + StructuredData::ObjectSP object_sp = GetInterface().CreatePluginObject( + m_scripted_process_info.GetClassName().c_str(), target_sp, + m_scripted_process_info.GetDictionarySP()); + + if (!object_sp || !object_sp->IsValid()) { + error.SetErrorStringWithFormat("ScriptedProcess::%s () - ERROR: %s", + __FUNCTION__, + "Failed to create valid script object"); + return; + } + + m_script_object_sp = object_sp; +} + +ScriptedProcess::~ScriptedProcess() { + Clear(); + // We need to call finalize on the process before destroying ourselves to + // make sure all of the broadcaster cleanup goes as planned. If we destruct + // this class, then Process::~Process() might have problems trying to fully + // destroy the broadcaster. + Finalize(); +} + +void ScriptedProcess::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); + }); +} + +void ScriptedProcess::Terminate() { + PluginManager::UnregisterPlugin(ScriptedProcess::CreateInstance); +} + +ConstString ScriptedProcess::GetPluginName() { return GetPluginNameStatic(); } + +uint32_t ScriptedProcess::GetPluginVersion() { return 1; } + +Status ScriptedProcess::DoLoadCore() { + ProcessLaunchInfo launch_info = GetTarget().GetProcessLaunchInfo(); + + return DoLaunch(nullptr, launch_info); +} + +Status ScriptedProcess::DoLaunch(Module *exe_module, + ProcessLaunchInfo &launch_info) { + CheckInterpreterAndScriptObject(); + + /* FIXME: This doesn't reflect how lldb actually launches a process. + In reality, it attaches to debugserver, then resume the process. */ + Status error = GetInterface().Launch(); + SetPrivateState(eStateRunning); + + if (error.Fail()) + return error; + + // TODO: Fetch next state from stopped event queue then send stop event + // const StateType state = SetThreadStopInfo(response); + // if (state != eStateInvalid) { + // SetPrivateState(state); + + SetPrivateState(eStateStopped); + + UpdateThreadListIfNeeded(); + GetThreadList(); + + return {}; +} + +void ScriptedProcess::DidLaunch() { + CheckInterpreterAndScriptObject(); + m_pid = GetInterface().GetProcessID(); +} + +Status ScriptedProcess::DoResume() { + CheckInterpreterAndScriptObject(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + // FIXME: Fetch data from thread. + const StateType thread_resume_state = eStateRunning; + LLDB_LOGF(log, "ScriptedProcess::%s thread_resume_state = %s", __FUNCTION__, + StateAsCString(thread_resume_state)); + + bool resume = (thread_resume_state == eStateRunning); + assert(thread_resume_state == eStateRunning && "invalid thread resume state"); + + Status error; + if (resume) { + LLDB_LOGF(log, "ScriptedProcess::%s sending resume", __FUNCTION__); + + SetPrivateState(eStateRunning); + SetPrivateState(eStateStopped); + error = GetInterface().Resume(); + } + + return error; +} + +Status ScriptedProcess::DoStop() { + CheckInterpreterAndScriptObject(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + if (GetInterface().ShouldStop()) { + SetPrivateState(eStateStopped); + LLDB_LOGF(log, "ScriptedProcess::%s Immediate stop", __FUNCTION__); + return {}; + } + + LLDB_LOGF(log, "ScriptedProcess::%s Delayed stop", __FUNCTION__); + return GetInterface().Stop(); +} + +Status ScriptedProcess::DoDestroy() { return Status(); } + +bool ScriptedProcess::IsAlive() { + if (m_interpreter && m_script_object_sp) + return GetInterface().IsAlive(); + return false; +} + +size_t ScriptedProcess::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Status &error) { + + auto error_with_message = [&error](llvm::StringRef message) { + error.SetErrorString(message); + return 0; + }; + + if (!m_interpreter) + return error_with_message("No interpreter."); + + lldb::DataExtractorSP data_extractor_sp = + GetInterface().ReadMemoryAtAddress(addr, size, error); + + if (!data_extractor_sp || error.Fail()) + return 0; + + offset_t bytes_copied = data_extractor_sp->CopyByteOrderedData( + 0, data_extractor_sp->GetByteSize(), buf, size, GetByteOrder()); + + if (!bytes_copied || bytes_copied == LLDB_INVALID_OFFSET) + return error_with_message("Failed to copy read memory to buffer."); + + return size; +} + +ArchSpec ScriptedProcess::GetArchitecture() { + return GetTarget().GetArchitecture(); +} + +Status ScriptedProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo ®ion) { + // TODO: Implement + return Status(); +} + +Status ScriptedProcess::GetMemoryRegions(MemoryRegionInfos ®ion_list) { + CheckInterpreterAndScriptObject(); + + lldb::addr_t address = 0; + lldb::MemoryRegionInfoSP mem_region_sp = nullptr; + + while ((mem_region_sp = + GetInterface().GetMemoryRegionContainingAddress(address))) { + auto range = mem_region_sp->GetRange(); + address += range.GetRangeBase() + range.GetByteSize(); + region_list.push_back(*mem_region_sp.get()); + } + + return {}; +} + +void ScriptedProcess::Clear() { Process::m_thread_list.Clear(); } + +bool ScriptedProcess::DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) { + // TODO: Implement + // This is supposed to get the current set of threads, if any of them are in + // old_thread_list then they get copied to new_thread_list, and then any + // actually new threads will get added to new_thread_list. + return new_thread_list.GetSize(false) > 0; +} + +bool ScriptedProcess::GetProcessInfo(ProcessInstanceInfo &info) { + info.Clear(); + info.SetProcessID(GetID()); + info.SetArchitecture(GetArchitecture()); + lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); + if (module_sp) { + const bool add_exe_file_as_first_arg = false; + info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), + add_exe_file_as_first_arg); + } + return true; +} + +ScriptedProcessInterface &ScriptedProcess::GetInterface() const { + return m_interpreter->GetScriptedProcessInterface(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h new file mode 100644 index 000000000000..98c1a1ca4fe9 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Process/scripted/ScriptedProcess.h @@ -0,0 +1,119 @@ +//===-- ScriptedProcess.h ------------------------------------- -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H +#define LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H + +#include "lldb/Target/Process.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Status.h" + +#include <mutex> + +namespace lldb_private { + +class ScriptedProcess : public Process { +protected: + class ScriptedProcessInfo { + public: + ScriptedProcessInfo(const ProcessLaunchInfo &launch_info) { + m_class_name = launch_info.GetScriptedProcessClassName(); + m_dictionary_sp = launch_info.GetScriptedProcessDictionarySP(); + } + + std::string GetClassName() const { return m_class_name; } + StructuredData::DictionarySP GetDictionarySP() const { + return m_dictionary_sp; + } + + private: + std::string m_class_name; + StructuredData::DictionarySP m_dictionary_sp; + }; + +public: + static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, + lldb::ListenerSP listener_sp, + const FileSpec *crash_file_path, + bool can_connect); + + static void Initialize(); + + static void Terminate(); + + static ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + ScriptedProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const ScriptedProcess::ScriptedProcessInfo &launch_info, + Status &error); + + ~ScriptedProcess() override; + + bool CanDebug(lldb::TargetSP target_sp, + bool plugin_specified_by_name) override; + + DynamicLoader *GetDynamicLoader() override { return nullptr; } + + ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override; + + SystemRuntime *GetSystemRuntime() override { return nullptr; } + + Status DoLoadCore() override; + + Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override; + + void DidLaunch() override; + + Status DoResume() override; + + Status DoDestroy() override; + + void RefreshStateAfterStop() override{}; + + bool IsAlive() override; + + size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, + Status &error) override; + + ArchSpec GetArchitecture(); + + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + + Status + GetMemoryRegions(lldb_private::MemoryRegionInfos ®ion_list) override; + + bool GetProcessInfo(ProcessInstanceInfo &info) override; + +protected: + Status DoStop(); + + void Clear(); + + bool DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) override; + +private: + void CheckInterpreterAndScriptObject() const; + ScriptedProcessInterface &GetInterface() const; + static bool IsScriptLanguageSupported(lldb::ScriptLanguage language); + + // Member variables. + const ScriptedProcessInfo m_scripted_process_info; + lldb_private::ScriptInterpreter *m_interpreter = nullptr; + lldb_private::StructuredData::ObjectSP m_script_object_sp = nullptr; + //@} +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SCRIPTED_PROCESS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp index f14e2732f6eb..e99b7b88379a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp @@ -30,6 +30,9 @@ extern "C" llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction( lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::BreakpointLocationSP bp_loc_sp, StructuredDataImpl *extra_args_impl); +extern "C" llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp); + #if _MSC_VER #pragma warning (pop) #endif @@ -113,6 +116,32 @@ Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, bp_loc_sp, extra_args_impl); } +llvm::Error Lua::RegisterWatchpointCallback(void *baton, const char *body) { + lua_pushlightuserdata(m_lua_state, baton); + const char *fmt_str = "return function(frame, wp, ...) {0} end"; + std::string func_str = llvm::formatv(fmt_str, body).str(); + if (luaL_dostring(m_lua_state, func_str.c_str()) != LUA_OK) { + llvm::Error e = llvm::make_error<llvm::StringError>( + llvm::formatv("{0}", lua_tostring(m_lua_state, -1)), + llvm::inconvertibleErrorCode()); + // Pop error message from the stack. + lua_pop(m_lua_state, 2); + return e; + } + lua_settable(m_lua_state, LUA_REGISTRYINDEX); + return llvm::Error::success(); +} + +llvm::Expected<bool> +Lua::CallWatchpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, + lldb::WatchpointSP wp_sp) { + + lua_pushlightuserdata(m_lua_state, baton); + lua_gettable(m_lua_state, LUA_REGISTRYINDEX); + return LLDBSwigLuaWatchpointCallbackFunction(m_lua_state, stop_frame_sp, + wp_sp); +} + llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) { int error = luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer"); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h index 873440f0aab3..5daedf835b9b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h @@ -37,6 +37,10 @@ public: CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, lldb::BreakpointLocationSP bp_loc_sp, StructuredData::ObjectSP extra_args_sp); + llvm::Error RegisterWatchpointCallback(void *baton, const char *body); + llvm::Expected<bool> CallWatchpointCallback(void *baton, + lldb::StackFrameSP stop_frame_sp, + lldb::WatchpointSP wp_sp); llvm::Error LoadModule(llvm::StringRef filename); llvm::Error CheckSyntax(llvm::StringRef buffer); llvm::Error ChangeIO(FILE *out, FILE *err); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index 920e334f51aa..ef46401c8b46 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -58,7 +58,13 @@ public: const char *instructions = nullptr; switch (m_active_io_handler) { case eIOHandlerNone: + break; case eIOHandlerWatchpoint: + instructions = "Enter your Lua command(s). Type 'quit' to end.\n" + "The commands are compiled as the body of the following " + "Lua function\n" + "function (frame, wp) end\n"; + SetPrompt(llvm::StringRef("..> ")); break; case eIOHandlerBreakpoint: instructions = "Enter your Lua command(s). Type 'quit' to end.\n" @@ -78,7 +84,8 @@ public: StringList &lines) override { size_t last = lines.GetSize() - 1; if (IsQuitCommand(lines.GetStringAtIndex(last))) { - if (m_active_io_handler == eIOHandlerBreakpoint) + if (m_active_io_handler == eIOHandlerBreakpoint || + m_active_io_handler == eIOHandlerWatchpoint) lines.DeleteStringAtIndex(last); return true; } @@ -90,17 +97,19 @@ public: // Lua always errors out to incomplete code with '<eof>' return error_str.find("<eof>") == std::string::npos; } - // The breakpoint handler only exits with a explicit 'quit' - return m_active_io_handler != eIOHandlerBreakpoint; + // The breakpoint and watchpoint handler only exits with a explicit 'quit' + return m_active_io_handler != eIOHandlerBreakpoint && + m_active_io_handler != eIOHandlerWatchpoint; } void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { switch (m_active_io_handler) { case eIOHandlerBreakpoint: { - auto *bp_options_vec = static_cast<std::vector<BreakpointOptions *> *>( - io_handler.GetUserData()); - for (auto *bp_options : *bp_options_vec) { + auto *bp_options_vec = + static_cast<std::vector<std::reference_wrapper<BreakpointOptions>> *>( + io_handler.GetUserData()); + for (BreakpointOptions &bp_options : *bp_options_vec) { Status error = m_script_interpreter.SetBreakpointCommandCallback( bp_options, data.c_str()); if (error.Fail()) @@ -108,9 +117,13 @@ public: } io_handler.SetIsDone(true); } break; - case eIOHandlerWatchpoint: + case eIOHandlerWatchpoint: { + auto *wp_options = + static_cast<WatchpointOptions *>(io_handler.GetUserData()); + m_script_interpreter.SetWatchpointCommandCallback(wp_options, + data.c_str()); io_handler.SetIsDone(true); - break; + } break; case eIOHandlerNone: if (IsQuitCommand(data)) { io_handler.SetIsDone(true); @@ -133,7 +146,7 @@ ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger) : ScriptInterpreter(debugger, eScriptLanguageLua), m_lua(std::make_unique<Lua>()) {} -ScriptInterpreterLua::~ScriptInterpreterLua() {} +ScriptInterpreterLua::~ScriptInterpreterLua() = default; bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command, CommandReturnObject *result, @@ -194,8 +207,9 @@ void ScriptInterpreterLua::ExecuteInterpreterLoop() { } bool ScriptInterpreterLua::LoadScriptingModule( - const char *filename, bool init_session, lldb_private::Status &error, - StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) { + const char *filename, const LoadScriptOptions &options, + lldb_private::Status &error, StructuredData::ObjectSP *module_sp, + FileSpec extra_search_dir) { FileSystem::Instance().Collect(filename); if (llvm::Error e = m_lua->LoadModule(filename)) { @@ -275,8 +289,35 @@ bool ScriptInterpreterLua::BreakpointCallbackFunction( return *BoolOrErr; } +bool ScriptInterpreterLua::WatchpointCallbackFunction( + void *baton, StoppointCallbackContext *context, user_id_t watch_id) { + assert(context); + + ExecutionContext exe_ctx(context->exe_ctx_ref); + Target *target = exe_ctx.GetTargetPtr(); + if (target == nullptr) + return true; + + StackFrameSP stop_frame_sp(exe_ctx.GetFrameSP()); + WatchpointSP wp_sp = target->GetWatchpointList().FindByID(watch_id); + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreterLua *lua_interpreter = static_cast<ScriptInterpreterLua *>( + debugger.GetScriptInterpreter(true, eScriptLanguageLua)); + Lua &lua = lua_interpreter->GetLua(); + + llvm::Expected<bool> BoolOrErr = + lua.CallWatchpointCallback(baton, stop_frame_sp, wp_sp); + if (llvm::Error E = BoolOrErr.takeError()) { + debugger.GetErrorStream() << toString(std::move(E)); + return true; + } + + return *BoolOrErr; +} + void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback( - std::vector<BreakpointOptions *> &bp_options_vec, + std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, CommandReturnObject &result) { IOHandlerSP io_handler_sp( new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerBreakpoint)); @@ -284,8 +325,16 @@ void ScriptInterpreterLua::CollectDataForBreakpointCommandCallback( m_debugger.RunIOHandlerAsync(io_handler_sp); } +void ScriptInterpreterLua::CollectDataForWatchpointCommandCallback( + WatchpointOptions *wp_options, CommandReturnObject &result) { + IOHandlerSP io_handler_sp( + new IOHandlerLuaInterpreter(m_debugger, *this, eIOHandlerWatchpoint)); + io_handler_sp->SetUserData(wp_options); + m_debugger.RunIOHandlerAsync(io_handler_sp); +} + Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction( - BreakpointOptions *bp_options, const char *function_name, + BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) { const char *fmt_str = "return {0}(frame, bp_loc, ...)"; std::string oneliner = llvm::formatv(fmt_str, function_name).str(); @@ -294,12 +343,12 @@ Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction( } Status ScriptInterpreterLua::SetBreakpointCommandCallback( - BreakpointOptions *bp_options, const char *command_body_text) { + BreakpointOptions &bp_options, const char *command_body_text) { return RegisterBreakpointCallback(bp_options, command_body_text, {}); } Status ScriptInterpreterLua::RegisterBreakpointCallback( - BreakpointOptions *bp_options, const char *command_body_text, + BreakpointOptions &bp_options, const char *command_body_text, StructuredData::ObjectSP extra_args_sp) { Status error; auto data_up = std::make_unique<CommandDataLua>(extra_args_sp); @@ -308,7 +357,27 @@ Status ScriptInterpreterLua::RegisterBreakpointCallback( return error; auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up)); - bp_options->SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction, + bp_options.SetCallback(ScriptInterpreterLua::BreakpointCallbackFunction, + baton_sp); + return error; +} + +void ScriptInterpreterLua::SetWatchpointCommandCallback( + WatchpointOptions *wp_options, const char *command_body_text) { + RegisterWatchpointCallback(wp_options, command_body_text, {}); +} + +Status ScriptInterpreterLua::RegisterWatchpointCallback( + WatchpointOptions *wp_options, const char *command_body_text, + StructuredData::ObjectSP extra_args_sp) { + Status error; + auto data_up = std::make_unique<WatchpointOptions::CommandData>(); + error = m_lua->RegisterWatchpointCallback(data_up.get(), command_body_text); + if (error.Fail()) + return error; + auto baton_sp = + std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); + wp_options->SetCallback(ScriptInterpreterLua::WatchpointCallbackFunction, baton_sp); return error; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h index 1130ceee3c20..808000b833ec 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h @@ -9,6 +9,9 @@ #ifndef liblldb_ScriptInterpreterLua_h_ #define liblldb_ScriptInterpreterLua_h_ +#include <vector> + +#include "lldb/Breakpoint/WatchpointOptions.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Utility/Status.h" @@ -40,7 +43,8 @@ public: void ExecuteInterpreterLoop() override; - bool LoadScriptingModule(const char *filename, bool init_session, + bool LoadScriptingModule(const char *filename, + const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp = nullptr, FileSpec extra_search_dir = {}) override; @@ -61,6 +65,10 @@ public: lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + static bool WatchpointCallbackFunction(void *baton, + StoppointCallbackContext *context, + lldb::user_id_t watch_id); + // PluginInterface protocol lldb_private::ConstString GetPluginName() override; @@ -72,21 +80,32 @@ public: llvm::Error LeaveSession(); void CollectDataForBreakpointCommandCallback( - std::vector<BreakpointOptions *> &bp_options_vec, + std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, CommandReturnObject &result) override; - Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, + void + CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options, + CommandReturnObject &result) override; + + Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *command_body_text) override; + void SetWatchpointCommandCallback(WatchpointOptions *wp_options, + const char *command_body_text) override; + Status SetBreakpointCommandCallbackFunction( - BreakpointOptions *bp_options, const char *function_name, + BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) override; private: std::unique_ptr<Lua> m_lua; bool m_session_is_active = false; - Status RegisterBreakpointCallback(BreakpointOptions *bp_options, + Status RegisterBreakpointCallback(BreakpointOptions &bp_options, + const char *command_body_text, + StructuredData::ObjectSP extra_args_sp); + + Status RegisterWatchpointCallback(WatchpointOptions *wp_options, const char *command_body_text, StructuredData::ObjectSP extra_args_sp); }; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp index d9c32cc132d4..f8a385240bd9 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp @@ -25,7 +25,7 @@ LLDB_PLUGIN_DEFINE(ScriptInterpreterNone) ScriptInterpreterNone::ScriptInterpreterNone(Debugger &debugger) : ScriptInterpreter(debugger, eScriptLanguageNone) {} -ScriptInterpreterNone::~ScriptInterpreterNone() {} +ScriptInterpreterNone::~ScriptInterpreterNone() = default; bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command, CommandReturnObject *, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 7c49502f1b57..f51d9b3a796c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -24,7 +24,7 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" -#include <stdio.h> +#include <cstdio> using namespace lldb_private; using namespace lldb; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 22f6c67eb7a5..4577253227cd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -229,7 +229,7 @@ struct PythonFormat< class PythonObject { public: - PythonObject() : m_py_obj(nullptr) {} + PythonObject() = default; PythonObject(PyRefType type, PyObject *py_obj) { m_py_obj = py_obj; @@ -378,7 +378,7 @@ public: } protected: - PyObject *m_py_obj; + PyObject *m_py_obj = nullptr; }; @@ -421,7 +421,7 @@ public: Py_DECREF(py_obj); } - TypedPythonObject() {} + TypedPythonObject() = default; }; class PythonBytes : public TypedPythonObject<PythonBytes> { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp index 5f6429f5cd0e..95a3365ed983 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp @@ -2,7 +2,7 @@ #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE -#include <stdio.h> +#include <cstdio> #include <editline/readline.h> diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp new file mode 100644 index 000000000000..7c7c5d73680a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp @@ -0,0 +1,48 @@ +//===-- SWIGPythonBridge.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "SWIGPythonBridge.h" + +using namespace lldb; + +namespace lldb_private { + +template <typename T> const char *GetPythonValueFormatString(T t); +template <> const char *GetPythonValueFormatString(char *) { return "s"; } +template <> const char *GetPythonValueFormatString(char) { return "b"; } +template <> const char *GetPythonValueFormatString(unsigned char) { + return "B"; +} +template <> const char *GetPythonValueFormatString(short) { return "h"; } +template <> const char *GetPythonValueFormatString(unsigned short) { + return "H"; +} +template <> const char *GetPythonValueFormatString(int) { return "i"; } +template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } +template <> const char *GetPythonValueFormatString(long) { return "l"; } +template <> const char *GetPythonValueFormatString(unsigned long) { + return "k"; +} +template <> const char *GetPythonValueFormatString(long long) { return "L"; } +template <> const char *GetPythonValueFormatString(unsigned long long) { + return "K"; +} +template <> const char *GetPythonValueFormatString(float) { return "f"; } +template <> const char *GetPythonValueFormatString(double) { return "d"; } + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h new file mode 100644 index 000000000000..1ef792bcf303 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -0,0 +1,56 @@ +//===-- ScriptInterpreterPython.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H + +#include <string> + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { + +// GetPythonValueFormatString provides a system independent type safe way to +// convert a variable's type into a python value format. Python value formats +// are defined in terms of builtin C types and could change from system to as +// the underlying typedef for uint* types, size_t, off_t and other values +// change. + +template <typename T> const char *GetPythonValueFormatString(T t); +template <> const char *GetPythonValueFormatString(char *); +template <> const char *GetPythonValueFormatString(char); +template <> const char *GetPythonValueFormatString(unsigned char); +template <> const char *GetPythonValueFormatString(short); +template <> const char *GetPythonValueFormatString(unsigned short); +template <> const char *GetPythonValueFormatString(int); +template <> const char *GetPythonValueFormatString(unsigned int); +template <> const char *GetPythonValueFormatString(long); +template <> const char *GetPythonValueFormatString(unsigned long); +template <> const char *GetPythonValueFormatString(long long); +template <> const char *GetPythonValueFormatString(unsigned long long); +template <> const char *GetPythonValueFormatString(float t); +template <> const char *GetPythonValueFormatString(double t); + +extern "C" void *LLDBSwigPythonCreateScriptedProcess( + const char *python_class_name, const char *session_dictionary_name, + const lldb::TargetSP &target_sp, StructuredDataImpl *args_impl, + std::string &error_string); + +extern "C" void *LLDBSWIGPython_CastPyObjectToSBData(void *data); +extern "C" void *LLDBSWIGPython_CastPyObjectToSBError(void *data); +extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); + +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 6b53bd3a2edc..7ad63722c31c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -16,7 +16,11 @@ #include "PythonDataObjects.h" #include "PythonReadline.h" +#include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" +#include "ScriptedProcessPythonInterface.h" + +#include "lldb/API/SBError.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" @@ -41,10 +45,10 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatAdapters.h" +#include <cstdio> +#include <cstdlib> #include <memory> #include <mutex> -#include <stdio.h> -#include <stdlib.h> #include <string> using namespace lldb; @@ -148,8 +152,6 @@ extern "C" void *LLDBSwigPython_GetChildAtIndex(void *implementor, extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor, const char *child_name); -extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data); - extern lldb::ValueObjectSP LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); @@ -234,8 +236,7 @@ namespace { // save off initial state at the beginning, and restore it at the end struct InitializePythonRAII { public: - InitializePythonRAII() - : m_gil_state(PyGILState_UNLOCKED), m_was_already_initialized(false) { + InitializePythonRAII() { InitializePythonHome(); #ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE @@ -355,8 +356,8 @@ private: } TerminalState m_stdin_tty_state; - PyGILState_STATE m_gil_state; - bool m_was_already_initialized; + PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; + bool m_was_already_initialized = false; }; } // namespace @@ -410,6 +411,32 @@ FileSpec ScriptInterpreterPython::GetPythonDir() { return g_spec; } +void ScriptInterpreterPython::SharedLibraryDirectoryHelper( + FileSpec &this_file) { + // When we're loaded from python, this_file will point to the file inside the + // python package directory. Replace it with the one in the lib directory. +#ifdef _WIN32 + // On windows, we need to manually back out of the python tree, and go into + // the bin directory. This is pretty much the inverse of what ComputePythonDir + // does. + if (this_file.GetFileNameExtension() == ConstString(".pyd")) { + this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd + this_file.RemoveLastPathComponent(); // lldb + llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR; + for (auto it = llvm::sys::path::begin(libdir), + end = llvm::sys::path::end(libdir); + it != end; ++it) + this_file.RemoveLastPathComponent(); + this_file.AppendPathComponent("bin"); + this_file.AppendPathComponent("liblldb.dll"); + } +#else + // The python file is a symlink, so we can find the real library by resolving + // it. We can do this unconditionally. + FileSystem::Instance().ResolveSymbolicLink(this_file, this_file); +#endif +} + lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() { static ConstString g_name("script-python"); return g_name; @@ -506,6 +533,9 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_command_thread_state(nullptr) { InitializePrivate(); + m_scripted_process_interface_up = + std::make_unique<ScriptedProcessPythonInterface>(*this); + m_dictionary_name.append("_dict"); StreamString run_string; run_string.Printf("%s = dict()", m_dictionary_name.c_str()); @@ -605,11 +635,10 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, case eIOHandlerNone: break; case eIOHandlerBreakpoint: { - std::vector<BreakpointOptions *> *bp_options_vec = - (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); - for (auto bp_options : *bp_options_vec) { - if (!bp_options) - continue; + std::vector<std::reference_wrapper<BreakpointOptions>> *bp_options_vec = + (std::vector<std::reference_wrapper<BreakpointOptions>> *) + io_handler.GetUserData(); + for (BreakpointOptions &bp_options : *bp_options_vec) { auto data_up = std::make_unique<CommandDataPython>(); if (!data_up) @@ -623,7 +652,7 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, .Success()) { auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>( std::move(data_up)); - bp_options->SetCallback( + bp_options.SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); } else if (!batch_mode) { StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); @@ -1048,11 +1077,24 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type, void *ret_value, const ExecuteScriptOptions &options) { + llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> + io_redirect_or_error = ScriptInterpreterIORedirect::Create( + options.GetEnableIO(), m_debugger, /*result=*/nullptr); + + if (!io_redirect_or_error) { + llvm::consumeError(io_redirect_or_error.takeError()); + return false; + } + + ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; + Locker locker(this, Locker::AcquireLock | Locker::InitSession | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | Locker::NoSTDIN, - Locker::FreeAcquiredLock | Locker::TearDownSession); + Locker::FreeAcquiredLock | Locker::TearDownSession, + io_redirect.GetInputFile(), io_redirect.GetOutputFile(), + io_redirect.GetErrorFile()); PythonModule &main_module = GetMainModule(); PythonDictionary globals = main_module.GetDictionary(); @@ -1161,11 +1203,22 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( if (in_string == nullptr) return Status(); + llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> + io_redirect_or_error = ScriptInterpreterIORedirect::Create( + options.GetEnableIO(), m_debugger, /*result=*/nullptr); + + if (!io_redirect_or_error) + return Status(io_redirect_or_error.takeError()); + + ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; + Locker locker(this, Locker::AcquireLock | Locker::InitSession | (options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) | Locker::NoSTDIN, - Locker::FreeAcquiredLock | Locker::TearDownSession); + Locker::FreeAcquiredLock | Locker::TearDownSession, + io_redirect.GetInputFile(), io_redirect.GetOutputFile(), + io_redirect.GetErrorFile()); PythonModule &main_module = GetMainModule(); PythonDictionary globals = main_module.GetDictionary(); @@ -1196,7 +1249,7 @@ Status ScriptInterpreterPythonImpl::ExecuteMultipleLines( } void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback( - std::vector<BreakpointOptions *> &bp_options_vec, + std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, CommandReturnObject &result) { m_active_io_handler = eIOHandlerBreakpoint; m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler( @@ -1211,7 +1264,7 @@ void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback( } Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( - BreakpointOptions *bp_options, const char *function_name, + BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) { Status error; // For now just cons up a oneliner that calls the provided function. @@ -1253,7 +1306,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( } Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( - BreakpointOptions *bp_options, + BreakpointOptions &bp_options, std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) { Status error; error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source, @@ -1264,21 +1317,20 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( } auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up)); - bp_options->SetCallback( + bp_options.SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); return error; } Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( - BreakpointOptions *bp_options, const char *command_body_text) { + BreakpointOptions &bp_options, const char *command_body_text) { return SetBreakpointCommandCallback(bp_options, command_body_text, {},false); } // Set a Python one-liner as the callback for the breakpoint. Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( - BreakpointOptions *bp_options, const char *command_body_text, - StructuredData::ObjectSP extra_args_sp, - bool uses_extra_args) { + BreakpointOptions &bp_options, const char *command_body_text, + StructuredData::ObjectSP extra_args_sp, bool uses_extra_args) { auto data_up = std::make_unique<CommandDataPython>(extra_args_sp); // Split the command_body_text into lines, and pass that to // GenerateBreakpointCommandCallbackData. That will wrap the body in an @@ -1292,7 +1344,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( if (error.Success()) { auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up)); - bp_options->SetCallback( + bp_options.SetCallback( ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp); return error; } @@ -1330,7 +1382,7 @@ Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( Status error = ExecuteMultipleLines( function_def_string.c_str(), - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); + ExecuteScriptOptions().SetEnableIO(false)); return error; } @@ -1678,35 +1730,6 @@ StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( return StructuredData::ArraySP(); } -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to as -// the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *) { return "s"; } -template <> const char *GetPythonValueFormatString(char) { return "b"; } -template <> const char *GetPythonValueFormatString(unsigned char) { - return "B"; -} -template <> const char *GetPythonValueFormatString(short) { return "h"; } -template <> const char *GetPythonValueFormatString(unsigned short) { - return "H"; -} -template <> const char *GetPythonValueFormatString(int) { return "i"; } -template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString(long) { return "l"; } -template <> const char *GetPythonValueFormatString(unsigned long) { - return "k"; -} -template <> const char *GetPythonValueFormatString(long long) { return "L"; } -template <> const char *GetPythonValueFormatString(unsigned long long) { - return "K"; -} -template <> const char *GetPythonValueFormatString(float t) { return "f"; } -template <> const char *GetPythonValueFormatString(double t) { return "d"; } - StructuredData::StringSP ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { @@ -2058,7 +2081,10 @@ ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec, StructuredData::ObjectSP module_sp; - if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp)) + LoadScriptOptions load_script_options = + LoadScriptOptions().SetInitSession(true).SetSilent(false); + if (LoadScriptingModule(file_spec.GetPath().c_str(), load_script_options, + error, &module_sp)) return module_sp; return StructuredData::ObjectSP(); @@ -2733,26 +2759,44 @@ uint64_t replace_all(std::string &str, const std::string &oldStr, } bool ScriptInterpreterPythonImpl::LoadScriptingModule( - const char *pathname, bool init_session, lldb_private::Status &error, - StructuredData::ObjectSP *module_sp, FileSpec extra_search_dir) { + const char *pathname, const LoadScriptOptions &options, + lldb_private::Status &error, StructuredData::ObjectSP *module_sp, + FileSpec extra_search_dir) { namespace fs = llvm::sys::fs; namespace path = llvm::sys::path; + ExecuteScriptOptions exc_options = ExecuteScriptOptions() + .SetEnableIO(!options.GetSilent()) + .SetSetLLDBGlobals(false); + if (!pathname || !pathname[0]) { error.SetErrorString("invalid pathname"); return false; } + llvm::Expected<std::unique_ptr<ScriptInterpreterIORedirect>> + io_redirect_or_error = ScriptInterpreterIORedirect::Create( + exc_options.GetEnableIO(), m_debugger, /*result=*/nullptr); + + if (!io_redirect_or_error) { + error = io_redirect_or_error.takeError(); + return false; + } + + ScriptInterpreterIORedirect &io_redirect = **io_redirect_or_error; lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); // Before executing Python code, lock the GIL. Locker py_lock(this, Locker::AcquireLock | - (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, + (options.GetInitSession() ? Locker::InitSession : 0) | + Locker::NoSTDIN, Locker::FreeAcquiredLock | - (init_session ? Locker::TearDownSession : 0)); + (options.GetInitSession() ? Locker::TearDownSession : 0), + io_redirect.GetInputFile(), io_redirect.GetOutputFile(), + io_redirect.GetErrorFile()); - auto ExtendSysPath = [this](std::string directory) -> llvm::Error { + auto ExtendSysPath = [&](std::string directory) -> llvm::Error { if (directory.empty()) { return llvm::make_error<llvm::StringError>( "invalid directory name", llvm::inconvertibleErrorCode()); @@ -2767,11 +2811,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( "sys.path.insert(1,'%s');\n\n", directory.c_str(), directory.c_str()); bool syspath_retval = - ExecuteMultipleLines(command_stream.GetData(), - ScriptInterpreter::ExecuteScriptOptions() - .SetEnableIO(false) - .SetSetLLDBGlobals(false)) - .Success(); + ExecuteMultipleLines(command_stream.GetData(), exc_options).Success(); if (!syspath_retval) { return llvm::make_error<llvm::StringError>( "Python sys.path handling failed", llvm::inconvertibleErrorCode()); @@ -2781,6 +2821,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( }; std::string module_name(pathname); + bool possible_package = false; if (extra_search_dir) { if (llvm::Error e = ExtendSysPath(extra_search_dir.GetPath())) { @@ -2805,6 +2846,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( return false; } // Not a filename, probably a package of some sort, let it go through. + possible_package = true; } else if (is_directory(st) || is_regular_file(st)) { if (module_file.GetDirectory().IsEmpty()) { error.SetErrorString("invalid directory name"); @@ -2831,35 +2873,39 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( module_name.resize(module_name.length() - 4); } - // check if the module is already import-ed + if (!possible_package && module_name.find('.') != llvm::StringRef::npos) { + error.SetErrorStringWithFormat( + "Python does not allow dots in module names: %s", module_name.c_str()); + return false; + } + + if (module_name.find('-') != llvm::StringRef::npos) { + error.SetErrorStringWithFormat( + "Python discourages dashes in module names: %s", module_name.c_str()); + return false; + } + + // Check if the module is already imported. StreamString command_stream; command_stream.Clear(); command_stream.Printf("sys.modules.__contains__('%s')", module_name.c_str()); bool does_contain = false; - // this call will succeed if the module was ever imported in any Debugger - // in the lifetime of the process in which this LLDB framework is living - bool was_imported_globally = - (ExecuteOneLineWithReturn( - command_stream.GetData(), - ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, - ScriptInterpreter::ExecuteScriptOptions() - .SetEnableIO(false) - .SetSetLLDBGlobals(false)) && - does_contain); - // this call will fail if the module was not imported in this Debugger - // before - command_stream.Clear(); - command_stream.Printf("sys.getrefcount(%s)", module_name.c_str()); - bool was_imported_locally = GetSessionDictionary() - .GetItemForKey(PythonString(module_name)) - .IsAllocated(); - - bool was_imported = (was_imported_globally || was_imported_locally); + // This call will succeed if the module was ever imported in any Debugger in + // the lifetime of the process in which this LLDB framework is living. + const bool does_contain_executed = ExecuteOneLineWithReturn( + command_stream.GetData(), + ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain, exc_options); + + const bool was_imported_globally = does_contain_executed && does_contain; + const bool was_imported_locally = + GetSessionDictionary() + .GetItemForKey(PythonString(module_name)) + .IsAllocated(); // now actually do the import command_stream.Clear(); - if (was_imported) { + if (was_imported_globally || was_imported_locally) { if (!was_imported_locally) command_stream.Printf("import %s ; reload_module(%s)", module_name.c_str(), module_name.c_str()); @@ -2868,10 +2914,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( } else command_stream.Printf("import %s", module_name.c_str()); - error = ExecuteMultipleLines(command_stream.GetData(), - ScriptInterpreter::ExecuteScriptOptions() - .SetEnableIO(false) - .SetSetLLDBGlobals(false)); + error = ExecuteMultipleLines(command_stream.GetData(), exc_options); if (error.Fail()) return false; @@ -2890,7 +2933,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( void *module_pyobj = nullptr; if (ExecuteOneLineWithReturn( command_stream.GetData(), - ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj) && + ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj, + exc_options) && module_pyobj) *module_sp = std::make_shared<StructuredPythonObject>(module_pyobj); } @@ -3047,7 +3091,7 @@ bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item, if (ExecuteOneLineWithReturn( command, ScriptInterpreter::eScriptReturnTypeCharStrOrNone, &result_ptr, - ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) { + ExecuteScriptOptions().SetEnableIO(false))) { if (result_ptr) dest.assign(result_ptr); return true; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index e59fedbd0971..b8b978118218 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -13,6 +13,8 @@ #if LLDB_ENABLE_PYTHON +#include "ScriptedProcessPythonInterface.h" + #include "lldb/Breakpoint/BreakpointOptions.h" #include "lldb/Core/IOHandler.h" #include "lldb/Core/StructuredDataImpl.h" @@ -51,6 +53,7 @@ public: static lldb_private::ConstString GetPluginNameStatic(); static const char *GetPluginDescriptionStatic(); static FileSpec GetPythonDir(); + static void SharedLibraryDirectoryHelper(FileSpec &this_file); protected: static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 45dad4217005..d1b0b3fda1ef 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -6,6 +6,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H + #include "lldb/Host/Config.h" #if LLDB_ENABLE_PYTHON @@ -231,7 +234,8 @@ public: bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value, std::string &output, Status &error) override; - bool LoadScriptingModule(const char *filename, bool init_session, + bool LoadScriptingModule(const char *filename, + const LoadScriptOptions &options, lldb_private::Status &error, StructuredData::ObjectSP *module_sp = nullptr, FileSpec extra_search_dir = {}) override; @@ -241,7 +245,7 @@ public: std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override; void CollectDataForBreakpointCommandCallback( - std::vector<BreakpointOptions *> &bp_options_vec, + std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec, CommandReturnObject &result) override; void @@ -249,20 +253,19 @@ public: CommandReturnObject &result) override; /// Set the callback body text into the callback for the breakpoint. - Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, + Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *callback_body) override; Status SetBreakpointCommandCallbackFunction( - BreakpointOptions *bp_options, - const char *function_name, + BreakpointOptions &bp_options, const char *function_name, StructuredData::ObjectSP extra_args_sp) override; /// This one is for deserialization: Status SetBreakpointCommandCallback( - BreakpointOptions *bp_options, + BreakpointOptions &bp_options, std::unique_ptr<BreakpointOptions::CommandData> &data_up) override; - Status SetBreakpointCommandCallback(BreakpointOptions *bp_options, + Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *command_body_text, StructuredData::ObjectSP extra_args_sp, bool uses_extra_args); @@ -416,7 +419,7 @@ public: : IOHandler(debugger, IOHandler::Type::PythonInterpreter), m_python(python) {} - ~IOHandlerPythonInterpreter() override {} + ~IOHandlerPythonInterpreter() override = default; ConstString GetControlSequence(char ch) override { if (ch == 'd') @@ -483,4 +486,5 @@ protected: } // namespace lldb_private -#endif +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp new file mode 100644 index 000000000000..ce262c930f8b --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -0,0 +1,306 @@ +//===-- ScriptedProcessPythonInterface.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "SWIGPythonBridge.h" +#include "ScriptInterpreterPythonImpl.h" +#include "ScriptedProcessPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( + const llvm::StringRef class_name, lldb::TargetSP target_sp, + StructuredData::DictionarySP args_sp) { + if (class_name.empty()) + return {}; + + std::string error_string; + StructuredDataImpl *args_impl = nullptr; + if (args_sp) { + args_impl = new StructuredDataImpl(); + args_impl->SetObjectSP(args_sp); + } + + void *ret_val; + + { + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + ret_val = LLDBSwigPythonCreateScriptedProcess( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, + args_impl, error_string); + } + + m_object_instance_sp = + StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + + return m_object_instance_sp; +} + +Status ScriptedProcessPythonInterface::Launch() { + return GetStatusFromMethod("launch"); +} + +Status ScriptedProcessPythonInterface::Resume() { + return GetStatusFromMethod("resume"); +} + +bool ScriptedProcessPythonInterface::ShouldStop() { + llvm::Optional<unsigned long long> should_stop = + GetGenericInteger("should_stop"); + + if (!should_stop) + return false; + + return static_cast<bool>(*should_stop); +} + +Status ScriptedProcessPythonInterface::Stop() { + return GetStatusFromMethod("stop"); +} + +Status ScriptedProcessPythonInterface::GetStatusFromMethod( + llvm::StringRef method_name) { + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + if (!m_object_instance_sp) + return Status("Python object ill-formed."); + + if (!m_object_instance_sp) + return Status("Cannot convert Python object to StructuredData::Generic."); + PythonObject implementor(PyRefType::Borrowed, + (PyObject *)m_object_instance_sp->GetValue()); + + if (!implementor.IsAllocated()) + return Status("Python implementor not allocated."); + + PythonObject pmeth( + PyRefType::Owned, + PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + + if (PyErr_Occurred()) + PyErr_Clear(); + + if (!pmeth.IsAllocated()) + return Status("Python method not allocated."); + + if (PyCallable_Check(pmeth.get()) == 0) { + if (PyErr_Occurred()) + PyErr_Clear(); + return Status("Python method not callable."); + } + + if (PyErr_Occurred()) + PyErr_Clear(); + + PythonObject py_return(PyRefType::Owned, + PyObject_CallMethod(implementor.get(), + method_name.str().c_str(), + nullptr)); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return Status("Python method could not be called."); + } + + if (PyObject *py_ret_ptr = py_return.get()) { + lldb::SBError *sb_error = + (lldb::SBError *)LLDBSWIGPython_CastPyObjectToSBError(py_ret_ptr); + + if (!sb_error) + return Status("Couldn't cast lldb::SBError to lldb::Status."); + + Status status = m_interpreter.GetStatusFromSBError(*sb_error); + + if (status.Fail()) + return Status("error: %s", status.AsCString()); + + return status; + } + + return Status("Returned object is null."); +} + +llvm::Optional<unsigned long long> +ScriptedProcessPythonInterface::GetGenericInteger(llvm::StringRef method_name) { + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + if (!m_object_instance_sp) + return llvm::None; + + if (!m_object_instance_sp) + return llvm::None; + PythonObject implementor(PyRefType::Borrowed, + (PyObject *)m_object_instance_sp->GetValue()); + + if (!implementor.IsAllocated()) + return llvm::None; + + PythonObject pmeth( + PyRefType::Owned, + PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + + if (PyErr_Occurred()) + PyErr_Clear(); + + if (!pmeth.IsAllocated()) + return llvm::None; + + if (PyCallable_Check(pmeth.get()) == 0) { + if (PyErr_Occurred()) + PyErr_Clear(); + return llvm::None; + } + + if (PyErr_Occurred()) + PyErr_Clear(); + + PythonObject py_return(PyRefType::Owned, + PyObject_CallMethod(implementor.get(), + method_name.str().c_str(), + nullptr)); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + + if (!py_return.get()) + return llvm::None; + + llvm::Expected<unsigned long long> size = py_return.AsUnsignedLongLong(); + // FIXME: Handle error. + if (!size) + return llvm::None; + + return *size; +} + +lldb::MemoryRegionInfoSP +ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( + lldb::addr_t address) { + // TODO: Implement + return nullptr; +} + +StructuredData::DictionarySP +ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { + // TODO: Implement + return nullptr; +} + +StructuredData::DictionarySP +ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { + // TODO: Implement + return nullptr; +} + +lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( + lldb::addr_t address, size_t size, Status &error) { + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + auto error_with_message = [&error](llvm::StringRef message) { + error.SetErrorString(message); + return nullptr; + }; + + static char callee_name[] = "read_memory_at_address"; + std::string param_format = GetPythonValueFormatString(address); + param_format += GetPythonValueFormatString(size); + + if (!m_object_instance_sp) + return error_with_message("Python object ill-formed."); + + if (!m_object_instance_sp) + return error_with_message("Python method not callable."); + + PythonObject implementor(PyRefType::Borrowed, + (PyObject *)m_object_instance_sp->GetValue()); + + if (!implementor.IsAllocated()) + return error_with_message("Python implementor not allocated."); + + PythonObject pmeth(PyRefType::Owned, + PyObject_GetAttrString(implementor.get(), callee_name)); + + if (PyErr_Occurred()) + PyErr_Clear(); + + if (!pmeth.IsAllocated()) + return error_with_message("Python method not allocated."); + + if (PyCallable_Check(pmeth.get()) == 0) { + if (PyErr_Occurred()) + PyErr_Clear(); + return error_with_message("Python method not callable."); + } + + if (PyErr_Occurred()) + PyErr_Clear(); + + PythonObject py_return(PyRefType::Owned, + PyObject_CallMethod(implementor.get(), callee_name, + param_format.c_str(), address, + size)); + + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + return error_with_message("Python method could not be called."); + } + + if (PyObject *py_ret_ptr = py_return.get()) { + lldb::SBData *sb_data = + (lldb::SBData *)LLDBSWIGPython_CastPyObjectToSBData(py_ret_ptr); + + if (!sb_data) + return error_with_message( + "Couldn't cast lldb::SBData to lldb::DataExtractor."); + + return m_interpreter.GetDataExtractorFromSBData(*sb_data); + } + + return error_with_message("Returned object is null."); +} + +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetLoadedImages() { + // TODO: Implement + return nullptr; +} + +lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { + llvm::Optional<unsigned long long> pid = GetGenericInteger("get_process_id"); + return (!pid) ? LLDB_INVALID_PROCESS_ID : *pid; +} + +bool ScriptedProcessPythonInterface::IsAlive() { + llvm::Optional<unsigned long long> is_alive = GetGenericInteger("is_alive"); + + if (!is_alive) + return false; + + return static_cast<bool>(*is_alive); +} + +#endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h new file mode 100644 index 000000000000..30cb5a882af2 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -0,0 +1,66 @@ +//===-- ScriptedProcessPythonInterface.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "lldb/Interpreter/ScriptedProcessInterface.h" + +namespace lldb_private { +class ScriptInterpreterPythonImpl; +class ScriptedProcessPythonInterface : public ScriptedProcessInterface { +public: + ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter) + : ScriptedProcessInterface(), m_interpreter(interpreter) {} + + StructuredData::GenericSP + CreatePluginObject(const llvm::StringRef class_name, lldb::TargetSP target_sp, + StructuredData::DictionarySP args_sp) override; + + Status Launch() override; + + Status Resume() override; + + bool ShouldStop() override; + + Status Stop() override; + + lldb::MemoryRegionInfoSP + GetMemoryRegionContainingAddress(lldb::addr_t address) override; + + StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; + + StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override; + + lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, + Status &error) override; + + StructuredData::DictionarySP GetLoadedImages() override; + + lldb::pid_t GetProcessID() override; + + bool IsAlive() override; + +protected: + llvm::Optional<unsigned long long> + GetGenericInteger(llvm::StringRef method_name); + Status GetStatusFromMethod(llvm::StringRef method_name); + +private: + // The lifetime is managed by the ScriptInterpreter + ScriptInterpreterPythonImpl &m_interpreter; + StructuredData::GenericSP m_object_instance_sp; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPROCESSPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp index f669e5873d2d..87edf7789f0d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp @@ -8,7 +8,7 @@ #include "StructuredDataDarwinLog.h" -#include <string.h> +#include <cstring> #include <memory> #include <sstream> @@ -126,7 +126,7 @@ public: m_collection_sp->Initialize(g_darwinlog_properties); } - ~StructuredDataDarwinLogProperties() override {} + ~StructuredDataDarwinLogProperties() override = default; bool GetEnableOnStartup() const { const uint32_t idx = ePropertyEnableOnStartup; @@ -181,7 +181,7 @@ using FilterRuleSP = std::shared_ptr<FilterRule>; class FilterRule { public: - virtual ~FilterRule() {} + virtual ~FilterRule() = default; using OperationCreationFunc = std::function<FilterRuleSP(bool accept, size_t attribute_index, @@ -473,13 +473,9 @@ static constexpr OptionDefinition g_enable_option_table[] = { class EnableOptions : public Options { public: EnableOptions() - : Options(), m_include_debug_level(false), m_include_info_level(false), - m_include_any_process(false), + : Options(), m_filter_fall_through_accepts(DEFAULT_FILTER_FALLTHROUGH_ACCEPTS), - m_echo_to_stderr(false), m_display_timestamp_relative(false), - m_display_subsystem(false), m_display_category(false), - m_display_activity_chain(false), m_broadcast_events(true), - m_live_stream(true), m_filter_rules() {} + m_filter_rules() {} void OptionParsingStarting(ExecutionContext *execution_context) override { m_include_debug_level = false; @@ -728,17 +724,17 @@ private: return -1; } - bool m_include_debug_level; - bool m_include_info_level; - bool m_include_any_process; + bool m_include_debug_level = false; + bool m_include_info_level = false; + bool m_include_any_process = false; bool m_filter_fall_through_accepts; - bool m_echo_to_stderr; - bool m_display_timestamp_relative; - bool m_display_subsystem; - bool m_display_category; - bool m_display_activity_chain; - bool m_broadcast_events; - bool m_live_stream; + bool m_echo_to_stderr = false; + bool m_display_timestamp_relative = false; + bool m_display_subsystem = false; + bool m_display_category = false; + bool m_display_activity_chain = false; + bool m_broadcast_events = true; + bool m_live_stream = true; FilterRules m_filter_rules; }; @@ -813,7 +809,6 @@ protected: StructuredDataDarwinLog::GetStaticPluginName())) { result.AppendError("failed to get StructuredDataPlugin for " "the process"); - result.SetStatus(eReturnStatusFailed); } StructuredDataDarwinLog &plugin = *static_cast<StructuredDataDarwinLog *>(plugin_sp.get()); @@ -837,7 +832,6 @@ protected: // Report results. if (!error.Success()) { result.AppendError(error.AsCString()); - result.SetStatus(eReturnStatusFailed); // Our configuration failed, so we're definitely disabled. plugin.SetEnabled(false); } else { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index 07e5b284eab8..b815ebb3c07a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -278,7 +278,7 @@ SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr, } uint32_t SymbolFileBreakpad::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); if (!(resolve_scope & eSymbolContextCompUnit)) @@ -287,8 +287,7 @@ uint32_t SymbolFileBreakpad::ResolveSymbolContext( uint32_t old_size = sc_list.GetSize(); for (size_t i = 0, size = GetNumCompileUnits(); i < size; ++i) { CompileUnit &cu = *GetCompileUnitAtIndex(i); - cu.ResolveSymbolContext(file_spec, line, check_inlines, - /*exact*/ false, resolve_scope, sc_list); + cu.ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); } return sc_list.GetSize() - old_size; } @@ -716,10 +715,10 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, llvm::Optional<addr_t> next_addr; auto finish_sequence = [&]() { LineTable::AppendLineEntryToSequence( - line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0, - /*file_idx*/ 0, /*is_start_of_statement*/ false, - /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, - /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true); + line_seq_up.get(), *next_addr, /*line=*/0, /*column=*/0, + /*file_idx=*/0, /*is_start_of_statement=*/false, + /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false, + /*is_epilogue_begin=*/false, /*is_terminal_entry=*/true); sequences.push_back(std::move(line_seq_up)); line_seq_up = LineTable::CreateLineSequenceContainer(); }; @@ -739,10 +738,10 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu, finish_sequence(); } LineTable::AppendLineEntryToSequence( - line_seq_up.get(), record->Address, record->LineNum, /*column*/ 0, - map[record->FileNum], /*is_start_of_statement*/ true, - /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false, - /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false); + line_seq_up.get(), record->Address, record->LineNum, /*column=*/0, + map[record->FileNum], /*is_start_of_statement=*/true, + /*is_start_of_basic_block=*/false, /*is_prologue_end=*/false, + /*is_epilogue_begin=*/false, /*is_terminal_entry=*/false); next_addr = record->Address + record->Size; } if (next_addr) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 90dbcc77627a..b0a35fa11de4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -51,7 +51,7 @@ public: SymbolFileBreakpad(lldb::ObjectFileSP objfile_sp) : SymbolFile(std::move(objfile_sp)) {} - ~SymbolFileBreakpad() override {} + ~SymbolFileBreakpad() override = default; uint32_t CalculateAbilities() override; @@ -101,8 +101,7 @@ public: lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override; - uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, - bool check_inlines, + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index 2e0a7fd3ecd3..ffe24836955f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -24,7 +24,7 @@ class SymbolFileDWARF; class DWARFASTParser { public: - virtual ~DWARFASTParser() {} + virtual ~DWARFASTParser() = default; virtual lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 188a667ca564..46015f7b43b1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <stdlib.h> +#include <cstdlib> #include "DWARFASTParserClang.h" #include "DWARFDebugInfo.h" @@ -49,7 +49,7 @@ //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF -#include <stdio.h> +#include <cstdio> #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) #else #define DEBUG_PRINTF(fmt, ...) @@ -60,7 +60,7 @@ using namespace lldb_private; DWARFASTParserClang::DWARFASTParserClang(TypeSystemClang &ast) : m_ast(ast), m_die_to_decl_ctx(), m_decl_ctx_to_die() {} -DWARFASTParserClang::~DWARFASTParserClang() {} +DWARFASTParserClang::~DWARFASTParserClang() = default; static AccessType DW_ACCESS_to_AccessType(uint32_t dwarf_accessibility) { switch (dwarf_accessibility) { @@ -157,7 +157,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, // The type in the Clang module must have the same language as the current CU. LanguageSet languages; - languages.Insert(SymbolFileDWARF::GetLanguage(*die.GetCU())); + languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())); llvm::DenseSet<SymbolFile *> searched_symbol_files; clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, searched_symbol_files, pcm_types); @@ -666,8 +666,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, // Blocks have a __FuncPtr inside them which is a pointer to a // function of the proper type. - for (DWARFDIE child_die = target_die.GetFirstChild(); - child_die.IsValid(); child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : target_die.children()) { if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), "__FuncPtr")) { DWARFDIE function_pointer_type = @@ -1226,6 +1225,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, } if (!function_decl) { + char *name_buf = nullptr; llvm::StringRef name = attrs.name.GetStringRef(); // We currently generate function templates with template parameters in @@ -1233,8 +1233,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, // we want to strip these from the name when creating the AST. if (attrs.mangled_name) { llvm::ItaniumPartialDemangler D; - if (!D.partialDemangle(attrs.mangled_name)) - name = D.getFunctionBaseName(nullptr, nullptr); + if (!D.partialDemangle(attrs.mangled_name)) { + name_buf = D.getFunctionBaseName(nullptr, nullptr); + name = name_buf; + } } // We just have a function that isn't part of a class @@ -1243,6 +1245,7 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, : containing_decl_ctx, GetOwningClangModule(die), name, clang_type, attrs.storage, attrs.is_inline); + std::free(name_buf); if (has_template_params) { TypeSystemClang::TemplateParameterInfos template_param_infos; @@ -1266,13 +1269,10 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, LinkDeclContextToDIE(function_decl, die); if (!function_param_decls.empty()) { - m_ast.SetFunctionParameters(function_decl, - &function_param_decls.front(), - function_param_decls.size()); + m_ast.SetFunctionParameters(function_decl, function_param_decls); if (template_function_decl) m_ast.SetFunctionParameters(template_function_decl, - &function_param_decls.front(), - function_param_decls.size()); + function_param_decls); } ClangASTMetadata metadata; @@ -1357,7 +1357,7 @@ TypeSP DWARFASTParserClang::ParsePointerToMemberType( dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true); CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType(); - CompilerType class_clang_type = class_type->GetLayoutCompilerType(); + CompilerType class_clang_type = class_type->GetForwardCompilerType(); CompilerType clang_type = TypeSystemClang::CreateMemberPointerType( class_clang_type, pointee_clang_type); @@ -1684,14 +1684,18 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, die.GetOffset(), attrs.name.GetCString()); } - if (tag == DW_TAG_structure_type) // this only applies in C - { + // If the byte size of the record is specified then overwrite the size + // that would be computed by Clang. This is only needed as LLDB's + // TypeSystemClang is always in C++ mode, but some compilers such as + // GCC and Clang give empty structs a size of 0 in C mode (in contrast to + // the size of 1 for empty structs that would be computed in C++ mode). + if (attrs.byte_size) { clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(clang_type); - if (record_decl) { - GetClangASTImporter().SetRecordLayout( - record_decl, ClangASTImporter::LayoutInfo()); + ClangASTImporter::LayoutInfo layout; + layout.bit_size = *attrs.byte_size * 8; + GetClangASTImporter().SetRecordLayout(record_decl, layout); } } } else if (clang_type_was_created) { @@ -1822,8 +1826,7 @@ bool DWARFASTParserClang::ParseTemplateDIE( case DW_TAG_GNU_template_parameter_pack: { template_param_infos.packed_args = std::make_unique<TypeSystemClang::TemplateParameterInfos>(); - for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { if (!ParseTemplateDIE(child_die, *template_param_infos.packed_args)) return false; } @@ -1928,8 +1931,7 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos( if (!parent_die) return false; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); switch (tag) { @@ -1978,15 +1980,12 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, } std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases; - std::vector<int> member_accessibilities; - bool is_a_class = false; // Parse members and base classes first std::vector<DWARFDIE> member_function_dies; DelayedPropertyList delayed_properties; - ParseChildMembers(die, clang_type, bases, member_accessibilities, - member_function_dies, delayed_properties, - default_accessibility, is_a_class, layout_info); + ParseChildMembers(die, clang_type, bases, member_function_dies, + delayed_properties, default_accessibility, layout_info); // Now parse any methods if there were any... for (const DWARFDIE &die : member_function_dies) @@ -2007,31 +2006,6 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, } } - // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we - // need to tell the clang type it is actually a class. - if (!type_is_objc_object_or_interface) { - if (is_a_class && tag_decl_kind != clang::TTK_Class) - m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type), - clang::TTK_Class); - } - - // Since DW_TAG_structure_type gets used for both classes and - // structures, we may need to set any DW_TAG_member fields to have a - // "private" access if none was specified. When we parsed the child - // members we tracked that actual accessibility value for each - // DW_TAG_member in the "member_accessibilities" array. If the value - // for the member is zero, then it was set to the - // "default_accessibility" which for structs was "public". Below we - // correct this by setting any fields to "private" that weren't - // correctly set. - if (is_a_class && !member_accessibilities.empty()) { - // This is a class and all members that didn't have their access - // specified are private. - m_ast.SetDefaultAccessForRecordFields( - m_ast.GetAsRecordDecl(clang_type), eAccessPrivate, - &member_accessibilities.front(), member_accessibilities.size()); - } - if (!bases.empty()) { // Make sure all base classes refer to complete types and not forward // declarations. If we don't do this, clang will crash with an @@ -2131,8 +2105,7 @@ void DWARFASTParserClang::EnsureAllDIEsInDeclContextHaveBeenParsed( for (auto it = m_decl_ctx_to_die.find(opaque_decl_ctx); it != m_decl_ctx_to_die.end() && it->first == opaque_decl_ctx; it = m_decl_ctx_to_die.erase(it)) - for (DWARFDIE decl = it->second.GetFirstChild(); decl; - decl = decl.GetSibling()) + for (DWARFDIE decl : it->second.children()) GetClangDeclForDIE(decl); } @@ -2168,8 +2141,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators( size_t enumerators_added = 0; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); if (tag == DW_TAG_enumerator) { DWARFAttributes attributes; @@ -2201,7 +2173,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators( case DW_AT_description: default: case DW_AT_decl_file: - decl.SetFile(die.GetCU()->GetFile(form_value.Unsigned())); + decl.SetFile(attributes.CompileUnitAtIndex(i)->GetFile( + form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); @@ -2343,7 +2316,6 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit, void DWARFASTParserClang::ParseSingleMember( const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, - std::vector<int> &member_accessibilities, lldb::AccessType default_accessibility, DelayedPropertyList &delayed_properties, lldb_private::ClangASTImporter::LayoutInfo &layout_info, @@ -2533,7 +2505,7 @@ void DWARFASTParserClang::ParseSingleMember( if (accessibility == eAccessNone) accessibility = eAccessPublic; TypeSystemClang::AddVariableToRecordType( - class_clang_type, name, var_type->GetLayoutCompilerType(), + class_clang_type, name, var_type->GetForwardCompilerType(), accessibility); } return; @@ -2551,7 +2523,6 @@ void DWARFASTParserClang::ParseSingleMember( if (accessibility == eAccessNone) accessibility = default_accessibility; - member_accessibilities.push_back(accessibility); uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); @@ -2666,7 +2637,7 @@ void DWARFASTParserClang::ParseSingleMember( last_field_info.bit_offset = field_bit_offset; if (llvm::Optional<uint64_t> clang_type_size = - member_clang_type.GetByteSize(nullptr)) { + member_type->GetByteSize(nullptr)) { last_field_info.bit_size = *clang_type_size * character_width; } @@ -2761,10 +2732,9 @@ void DWARFASTParserClang::ParseSingleMember( bool DWARFASTParserClang::ParseChildMembers( const DWARFDIE &parent_die, CompilerType &class_clang_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, - std::vector<int> &member_accessibilities, std::vector<DWARFDIE> &member_function_dies, DelayedPropertyList &delayed_properties, AccessType &default_accessibility, - bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) { + ClangASTImporter::LayoutInfo &layout_info) { if (!parent_die) return false; @@ -2776,16 +2746,15 @@ bool DWARFASTParserClang::ParseChildMembers( if (ast == nullptr) return false; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { dw_tag_t tag = die.Tag(); switch (tag) { case DW_TAG_member: case DW_TAG_APPLE_property: ParseSingleMember(die, parent_die, class_clang_type, - member_accessibilities, default_accessibility, - delayed_properties, layout_info, last_field_info); + default_accessibility, delayed_properties, layout_info, + last_field_info); break; case DW_TAG_subprogram: @@ -2794,9 +2763,6 @@ bool DWARFASTParserClang::ParseChildMembers( break; case DW_TAG_inheritance: { - is_a_class = true; - if (default_accessibility == eAccessNone) - default_accessibility = eAccessPrivate; // TODO: implement DW_TAG_inheritance type parsing DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes(attributes); @@ -2926,8 +2892,7 @@ size_t DWARFASTParserClang::ParseChildParameters( return 0; size_t arg_idx = 0; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); switch (tag) { case DW_TAG_formal_parameter: { @@ -3046,8 +3011,7 @@ DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, if (!parent_die) return llvm::None; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { const dw_tag_t tag = die.Tag(); if (tag != DW_TAG_subrange_type) continue; @@ -3349,8 +3313,7 @@ static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) { } static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) { - for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid(); - candidate = candidate.GetSibling()) { + for (DWARFDIE candidate : context.children()) { if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) { return candidate; } @@ -3514,8 +3477,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( UniqueCStringMap<DWARFDIE> dst_name_to_die; UniqueCStringMap<DWARFDIE> src_name_to_die_artificial; UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial; - for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); - src_die = src_die.GetSibling()) { + for (DWARFDIE src_die : src_class_die.children()) { if (src_die.Tag() == DW_TAG_subprogram) { // Make sure this is a declaration and not a concrete instance by looking // for DW_AT_declaration set to 1. Sometimes concrete function instances @@ -3533,8 +3495,7 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes( } } } - for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); - dst_die = dst_die.GetSibling()) { + for (DWARFDIE dst_die : dst_class_die.children()) { if (dst_die.Tag() == DW_TAG_subprogram) { // Make sure this is a declaration and not a concrete instance by looking // for DW_AT_declaration set to 1. Sometimes concrete function instances diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index e13716b95c1c..9bf6240b7554 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -111,10 +111,9 @@ protected: bool ParseChildMembers( const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, - std::vector<int> &member_accessibilities, std::vector<DWARFDIE> &member_function_dies, DelayedPropertyList &delayed_properties, - lldb::AccessType &default_accessibility, bool &is_a_class, + lldb::AccessType &default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t @@ -194,7 +193,6 @@ private: void ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, - std::vector<int> &member_accessibilities, lldb::AccessType default_accessibility, DelayedPropertyList &delayed_properties, lldb_private::ClangASTImporter::LayoutInfo &layout_info, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp index 0e9370be15fb..2f6b36c79b80 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp @@ -17,9 +17,7 @@ using namespace lldb_private; -DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() - : m_code(InvalidCode), m_tag(llvm::dwarf::DW_TAG_null), m_has_children(0), - m_attributes() {} +DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() : m_attributes() {} DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) @@ -58,7 +56,7 @@ DWARFAbbreviationDeclaration::extract(const DWARFDataExtractor &data, DWARFFormValue::ValueType val; if (form == DW_FORM_implicit_const) - val.value.sval = data.GetULEB128(offset_ptr); + val.value.sval = data.GetSLEB128(offset_ptr); m_attributes.push_back(DWARFAttribute(attr, form, val)); } @@ -82,9 +80,3 @@ DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const { } return DW_INVALID_INDEX; } - -bool DWARFAbbreviationDeclaration:: -operator==(const DWARFAbbreviationDeclaration &rhs) const { - return Tag() == rhs.Tag() && HasChildren() == rhs.HasChildren() && - m_attributes == rhs.m_attributes; -} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h index f70aa71a5958..378ba888f4e0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h @@ -53,12 +53,11 @@ public: extract(const lldb_private::DWARFDataExtractor &data, lldb::offset_t *offset_ptr); bool IsValid(); - bool operator==(const DWARFAbbreviationDeclaration &rhs) const; protected: - dw_uleb128_t m_code; - dw_tag_t m_tag; - uint8_t m_has_children; + dw_uleb128_t m_code = InvalidCode; + dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; + uint8_t m_has_children = 0; DWARFAttribute::collection m_attributes; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp index ef98d7e33a90..134f6b2bd114 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -12,7 +12,7 @@ DWARFAttributes::DWARFAttributes() : m_infos() {} -DWARFAttributes::~DWARFAttributes() {} +DWARFAttributes::~DWARFAttributes() = default; uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const { collection::const_iterator end = m_infos.end(); @@ -25,10 +25,11 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const { return UINT32_MAX; } -void DWARFAttributes::Append(DWARFUnit *cu, dw_offset_t attr_die_offset, - dw_attr_t attr, dw_form_t form) { - AttributeValue attr_value = { - cu, attr_die_offset, {attr, form, DWARFFormValue::ValueType()}}; +void DWARFAttributes::Append(const DWARFFormValue &form_value, + dw_offset_t attr_die_offset, dw_attr_t attr) { + AttributeValue attr_value = {const_cast<DWARFUnit *>(form_value.GetUnit()), + attr_die_offset, + {attr, form_value.Form(), form_value.Value()}}; m_infos.push_back(attr_value); } @@ -37,6 +38,10 @@ bool DWARFAttributes::ExtractFormValueAtIndex( const DWARFUnit *cu = CompileUnitAtIndex(i); form_value.SetUnit(cu); form_value.SetForm(FormAtIndex(i)); + if (form_value.Form() == DW_FORM_implicit_const) { + form_value.SetValue(ValueAtIndex(i)); + return true; + } lldb::offset_t offset = DIEOffsetAtIndex(i); return form_value.ExtractValue(cu->GetData(), &offset); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h index 8c21404610d7..a31ee861179c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -22,21 +22,15 @@ public: DWARFFormValue::ValueType value) : m_attr(attr), m_form(form), m_value(value) {} - void set(dw_attr_t attr, dw_form_t form) { - m_attr = attr; - m_form = form; - } dw_attr_t get_attr() const { return m_attr; } dw_form_t get_form() const { return m_form; } + DWARFFormValue::ValueType get_value() const { return m_value; } void get(dw_attr_t &attr, dw_form_t &form, DWARFFormValue::ValueType &val) const { attr = m_attr; form = m_form; val = m_value; } - bool operator==(const DWARFAttribute &rhs) const { - return m_attr == rhs.m_attr && m_form == rhs.m_form; - } typedef std::vector<DWARFAttribute> collection; typedef collection::iterator iterator; typedef collection::const_iterator const_iterator; @@ -52,8 +46,8 @@ public: DWARFAttributes(); ~DWARFAttributes(); - void Append(DWARFUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, - dw_form_t form); + void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset, + dw_attr_t attr); DWARFUnit *CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; } dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; @@ -62,6 +56,9 @@ public: return m_infos[i].attr.get_attr(); } dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); } + DWARFFormValue::ValueType ValueAtIndex(uint32_t i) const { + return m_infos[i].attr.get_value(); + } bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const; DWARFDIE FormValueAsReferenceAtIndex(uint32_t i) const; DWARFDIE FormValueAsReference(dw_attr_t attr) const; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h index 059b84864be7..36df980f6ef0 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h @@ -24,7 +24,7 @@ class SymbolFileDWARF; class DWARFBaseDIE { public: - DWARFBaseDIE() : m_cu(nullptr), m_die(nullptr) {} + DWARFBaseDIE() = default; DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die) : m_cu(cu), m_die(die) {} @@ -115,8 +115,8 @@ public: Recurse recurse = Recurse::yes) const; protected: - DWARFUnit *m_cu; - DWARFDebugInfoEntry *m_die; + DWARFUnit *m_cu = nullptr; + DWARFDebugInfoEntry *m_die = nullptr; }; bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 8e995e627978..dda691eecacc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -54,7 +54,7 @@ public: explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {} /// End marker - ElaboratingDIEIterator() {} + ElaboratingDIEIterator() = default; const DWARFDIE &operator*() const { return m_worklist.back(); } ElaboratingDIEIterator &operator++() { @@ -192,7 +192,7 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const { } if (check_children) { - for (DWARFDIE child = GetFirstChild(); child; child = child.GetSibling()) { + for (DWARFDIE child : children()) { if (DWARFDIE child_result = child.LookupDeepestBlock(address)) return child_result; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index 13737280926c..56154055c44d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -11,9 +11,11 @@ #include "DWARFBaseDIE.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/iterator_range.h" class DWARFDIE : public DWARFBaseDIE { public: + class child_iterator; using DWARFBaseDIE::DWARFBaseDIE; // Tests @@ -88,6 +90,47 @@ public: int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, lldb_private::DWARFExpression *frame_base) const; + /// The range of all the children of this DIE. + /// + /// This is a template just because child_iterator is not completely defined + /// at this point. + template <typename T = child_iterator> + llvm::iterator_range<T> children() const { + return llvm::make_range(T(*this), T()); + } +}; + +class DWARFDIE::child_iterator + : public llvm::iterator_facade_base<DWARFDIE::child_iterator, + std::forward_iterator_tag, DWARFDIE> { + /// The current child or an invalid DWARFDie. + DWARFDIE m_die; + +public: + child_iterator() = default; + child_iterator(const DWARFDIE &parent) : m_die(parent.GetFirstChild()) {} + bool operator==(const child_iterator &it) const { + // DWARFDIE's operator== differentiates between an invalid DWARFDIE that + // has a CU but no DIE and one that has neither CU nor DIE. The 'end' + // iterator could be default constructed, so explicitly allow + // (CU, (DIE)nullptr) == (nullptr, nullptr) -> true + if (!m_die.IsValid() && !it.m_die.IsValid()) + return true; + return m_die == it.m_die; + } + const DWARFDIE &operator*() const { + assert(m_die.IsValid() && "Derefencing invalid iterator?"); + return m_die; + } + DWARFDIE &operator*() { + assert(m_die.IsValid() && "Derefencing invalid iterator?"); + return m_die; + } + child_iterator &operator++() { + assert(m_die.IsValid() && "Incrementing invalid iterator?"); + m_die = m_die.GetSibling(); + return *this; + } }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDIE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h index 555864f44967..ec6b93ce0e7f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h @@ -26,8 +26,7 @@ typedef DWARFAbbreviationDeclarationColl::const_iterator class DWARFAbbreviationDeclarationSet { public: - DWARFAbbreviationDeclarationSet() - : m_offset(DW_INVALID_OFFSET), m_idx_offset(0), m_decls() {} + DWARFAbbreviationDeclarationSet() : m_offset(DW_INVALID_OFFSET), m_decls() {} DWARFAbbreviationDeclarationSet(dw_offset_t offset, uint32_t idx_offset) : m_offset(offset), m_idx_offset(idx_offset), m_decls() {} @@ -51,7 +50,7 @@ public: /// @} private: dw_offset_t m_offset; - uint32_t m_idx_offset; + uint32_t m_idx_offset = 0; std::vector<DWARFAbbreviationDeclaration> m_decls; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp index 728cefe620a5..ce514381ee39 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp @@ -8,22 +8,18 @@ #include "DWARFDebugArangeSet.h" #include "DWARFDataExtractor.h" +#include "LogChannelDWARF.h" #include "llvm/Object/Error.h" #include <cassert> using namespace lldb_private; DWARFDebugArangeSet::DWARFDebugArangeSet() - : m_offset(DW_INVALID_OFFSET), m_header(), m_arange_descriptors() { - m_header.length = 0; - m_header.version = 0; - m_header.cu_offset = 0; - m_header.addr_size = 0; - m_header.seg_size = 0; -} + : m_offset(DW_INVALID_OFFSET), m_next_offset(DW_INVALID_OFFSET) {} void DWARFDebugArangeSet::Clear() { m_offset = DW_INVALID_OFFSET; + m_next_offset = DW_INVALID_OFFSET; m_header.length = 0; m_header.version = 0; m_header.cu_offset = 0; @@ -54,6 +50,12 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data, // consists of an address and a length, each in the size appropriate for an // address on the target architecture. m_header.length = data.GetDWARFInitialLength(offset_ptr); + // The length could be 4 bytes or 12 bytes, so use the current offset to + // determine the next offset correctly. + if (m_header.length > 0) + m_next_offset = *offset_ptr + m_header.length; + else + m_next_offset = DW_INVALID_OFFSET; m_header.version = data.GetU16(offset_ptr); m_header.cu_offset = data.GetDWARFOffset(offset_ptr); m_header.addr_size = data.GetU8(offset_ptr); @@ -105,17 +107,45 @@ llvm::Error DWARFDebugArangeSet::extract(const DWARFDataExtractor &data, "DWARFDebugArangeSet::Descriptor.address and " "DWARFDebugArangeSet::Descriptor.length must have same size"); - while (data.ValidOffset(*offset_ptr)) { + const lldb::offset_t next_offset = GetNextOffset(); + assert(next_offset != DW_INVALID_OFFSET); + uint32_t num_terminators = 0; + bool last_was_terminator = false; + while (*offset_ptr < next_offset) { arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size); arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size); // Each set of tuples is terminated by a 0 for the address and 0 for - // the length. - if (!arangeDescriptor.address && !arangeDescriptor.length) - return llvm::ErrorSuccess(); - - m_arange_descriptors.push_back(arangeDescriptor); + // the length. Some linkers can emit .debug_aranges with multiple + // terminator pair entries that are still withing the length of the + // DWARFDebugArangeSet. We want to be sure to parse all entries for + // this DWARFDebugArangeSet so that we don't stop parsing early and end up + // treating addresses as a header of the next DWARFDebugArangeSet. We also + // need to make sure we parse all valid address pairs so we don't omit them + // from the aranges result, so we can't stop at the first terminator entry + // we find. + if (arangeDescriptor.address == 0 && arangeDescriptor.length == 0) { + ++num_terminators; + last_was_terminator = true; + } else { + last_was_terminator = false; + // Only add .debug_aranges address entries that have a non zero size. + // Some linkers will zero out the length field for some .debug_aranges + // entries if they were stripped. We also could watch out for multiple + // entries at address zero and remove those as well. + if (arangeDescriptor.length > 0) + m_arange_descriptors.push_back(arangeDescriptor); + } + } + if (num_terminators > 1) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG(log, + "warning: DWARFDebugArangeSet at %#" PRIx64 " contains %u " + "terminator entries", + m_offset, num_terminators); } + if (last_was_terminator) + return llvm::ErrorSuccess(); return llvm::make_error<llvm::object::GenericBinaryError>( "arange descriptors not terminated by null entry"); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h index 6b5b69a70a80..3c8633eaa3cc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h @@ -16,18 +16,21 @@ class DWARFDebugArangeSet { public: struct Header { - uint32_t length; // The total length of the entries for that set, not - // including the length field itself. - uint16_t version; // The DWARF version number - uint32_t cu_offset; // The offset from the beginning of the .debug_info - // section of the compilation unit entry referenced by - // the table. - uint8_t addr_size; // The size in bytes of an address on the target - // architecture. For segmented addressing, this is the - // size of the offset portion of the address - uint8_t seg_size; // The size in bytes of a segment descriptor on the target - // architecture. If the target system uses a flat address - // space, this value is 0. + /// The total length of the entries for that set, not including the length + /// field itself. + uint32_t length = 0; + /// The DWARF version number. + uint16_t version = 0; + /// The offset from the beginning of the .debug_info section of the + /// compilation unit entry referenced by the table. + uint32_t cu_offset = 0; + /// The size in bytes of an address on the target architecture. For + /// segmented addressing, this is the size of the offset portion of the + /// address. + uint8_t addr_size = 0; + /// The size in bytes of a segment descriptor on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t seg_size = 0; }; struct Descriptor { @@ -44,7 +47,7 @@ public: dw_offset_t FindAddress(dw_addr_t address) const; size_t NumDescriptors() const { return m_arange_descriptors.size(); } const Header &GetHeader() const { return m_header; } - + dw_offset_t GetNextOffset() const { return m_next_offset; } const Descriptor &GetDescriptorRef(uint32_t i) const { return m_arange_descriptors[i]; } @@ -54,7 +57,8 @@ protected: typedef DescriptorColl::iterator DescriptorIter; typedef DescriptorColl::const_iterator DescriptorConstIter; - uint32_t m_offset; + dw_offset_t m_offset; + dw_offset_t m_next_offset; Header m_header; DescriptorColl m_arange_descriptors; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index 9f190fbcee87..65923cb4ad6b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -9,6 +9,7 @@ #include "DWARFDebugAranges.h" #include "DWARFDebugArangeSet.h" #include "DWARFUnit.h" +#include "LogChannelDWARF.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/Timer.h" @@ -31,31 +32,40 @@ public: }; // Extract -llvm::Error -DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) { +void DWARFDebugAranges::extract(const DWARFDataExtractor &debug_aranges_data) { lldb::offset_t offset = 0; DWARFDebugArangeSet set; Range range; while (debug_aranges_data.ValidOffset(offset)) { - llvm::Error error = set.extract(debug_aranges_data, &offset); - if (error) - return error; + const lldb::offset_t set_offset = offset; + if (llvm::Error error = set.extract(debug_aranges_data, &offset)) { + Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); + LLDB_LOG_ERROR(log, std::move(error), + "DWARFDebugAranges::extract failed to extract " + ".debug_aranges set at offset %#" PRIx64, + set_offset); + } else { + const uint32_t num_descriptors = set.NumDescriptors(); + if (num_descriptors > 0) { + const dw_offset_t cu_offset = set.GetHeader().cu_offset; - const uint32_t num_descriptors = set.NumDescriptors(); - if (num_descriptors > 0) { - const dw_offset_t cu_offset = set.GetHeader().cu_offset; - - for (uint32_t i = 0; i < num_descriptors; ++i) { - const DWARFDebugArangeSet::Descriptor &descriptor = - set.GetDescriptorRef(i); - m_aranges.Append(RangeToDIE::Entry(descriptor.address, - descriptor.length, cu_offset)); + for (uint32_t i = 0; i < num_descriptors; ++i) { + const DWARFDebugArangeSet::Descriptor &descriptor = + set.GetDescriptorRef(i); + m_aranges.Append(RangeToDIE::Entry(descriptor.address, + descriptor.length, cu_offset)); + } } } + // Always use the previous DWARFDebugArangeSet's information to calculate + // the offset of the next DWARFDebugArangeSet in case we entouncter an + // error in the current DWARFDebugArangeSet and our offset position is + // still in the middle of the data. If we do this, we can parse all valid + // DWARFDebugArangeSet objects without returning invalid errors. + offset = set.GetNextOffset(); set.Clear(); } - return llvm::ErrorSuccess(); } void DWARFDebugAranges::Dump(Log *log) const { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h index 96e82619f985..5ff37e400c88 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -26,8 +26,7 @@ public: void Clear() { m_aranges.Clear(); } - llvm::Error - extract(const lldb_private::DWARFDataExtractor &debug_aranges_data); + void extract(const lldb_private::DWARFDataExtractor &debug_aranges_data); // Use append range multiple times and then call sort void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 8d393b295443..e43afa104413 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -34,17 +34,18 @@ DWARFDebugInfo::DWARFDebugInfo(SymbolFileDWARF &dwarf, lldb_private::DWARFContext &context) : m_dwarf(dwarf), m_context(context), m_units(), m_cu_aranges_up() {} -llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { +const DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { if (m_cu_aranges_up) return *m_cu_aranges_up; m_cu_aranges_up = std::make_unique<DWARFDebugAranges>(); const DWARFDataExtractor &debug_aranges_data = m_context.getOrLoadArangesData(); - if (llvm::Error error = m_cu_aranges_up->extract(debug_aranges_data)) - return std::move(error); - // Make a list of all CUs represented by the arange data in the file. + // Extract what we can from the .debug_aranges first. + m_cu_aranges_up->extract(debug_aranges_data); + + // Make a list of all CUs represented by the .debug_aranges data. std::set<dw_offset_t> cus_with_data; for (size_t n = 0; n < m_cu_aranges_up->GetNumRanges(); n++) { dw_offset_t offset = m_cu_aranges_up->OffsetAtIndex(n); @@ -52,8 +53,7 @@ llvm::Expected<DWARFDebugAranges &> DWARFDebugInfo::GetCompileUnitAranges() { cus_with_data.insert(offset); } - // Manually build arange data for everything that wasn't in the - // .debug_aranges table. + // Manually build arange data for everything that wasn't in .debug_aranges. const size_t num_units = GetNumUnits(); for (size_t idx = 0; idx < num_units; ++idx) { DWARFUnit *cu = GetUnitAtIndex(idx); @@ -72,16 +72,10 @@ void DWARFDebugInfo::ParseUnitsFor(DIERef::Section section) { DWARFDataExtractor data = section == DIERef::Section::DebugTypes ? m_context.getOrLoadDebugTypesData() : m_context.getOrLoadDebugInfoData(); - const llvm::DWARFUnitIndex *index = nullptr; - if (m_context.isDwo()) - index = &llvm::getDWARFUnitIndex(m_context.GetAsLLVM(), - section == DIERef::Section::DebugTypes - ? llvm::DW_SECT_EXT_TYPES - : llvm::DW_SECT_INFO); lldb::offset_t offset = 0; while (data.ValidOffset(offset)) { llvm::Expected<DWARFUnitSP> unit_sp = DWARFUnit::extract( - m_dwarf, m_units.size(), data, section, &offset, index); + m_dwarf, m_units.size(), data, section, &offset); if (!unit_sp) { // FIXME: Propagate this error up. diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index bdc718a5c2fa..46c04d749c46 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -54,7 +54,7 @@ public: (1 << 2) // Show all parent DIEs when dumping single DIEs }; - llvm::Expected<DWARFDebugAranges &> GetCompileUnitAranges(); + const DWARFDebugAranges &GetCompileUnitAranges(); protected: typedef std::vector<DWARFUnitSP> UnitColl; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 421298802645..39915aa889ff 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -8,7 +8,7 @@ #include "DWARFDebugInfoEntry.h" -#include <assert.h> +#include <cassert> #include <algorithm> @@ -49,156 +49,159 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, // assert (fixed_form_sizes); // For best performance this should be // specified! - if (m_abbr_idx) { - lldb::offset_t offset = *offset_ptr; - const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); - if (abbrevDecl == nullptr) { - cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " - "attach the file at the start of this error message", - m_offset, (unsigned)abbr_idx); - // WE can't parse anymore if the DWARF is borked... - *offset_ptr = UINT32_MAX; - return false; - } - m_tag = abbrevDecl->Tag(); - m_has_children = abbrevDecl->HasChildren(); - // Skip all data in the .debug_info or .debug_types for the attributes - const uint32_t numAttributes = abbrevDecl->NumAttributes(); - uint32_t i; - dw_form_t form; - for (i = 0; i < numAttributes; ++i) { - form = abbrevDecl->GetFormByIndexUnchecked(i); - llvm::Optional<uint8_t> fixed_skip_size = - DWARFFormValue::GetFixedSize(form, cu); - if (fixed_skip_size) - offset += *fixed_skip_size; - else { - bool form_is_indirect = false; - do { - form_is_indirect = false; - uint32_t form_size = 0; - switch (form) { - // Blocks if inlined data that have a length field and the data bytes - // inlined in the .debug_info/.debug_types - case DW_FORM_exprloc: - case DW_FORM_block: - form_size = data.GetULEB128(&offset); - break; - case DW_FORM_block1: - form_size = data.GetU8_unchecked(&offset); - break; - case DW_FORM_block2: - form_size = data.GetU16_unchecked(&offset); - break; - case DW_FORM_block4: - form_size = data.GetU32_unchecked(&offset); - break; - - // Inlined NULL terminated C-strings - case DW_FORM_string: - data.GetCStr(&offset); - break; - - // Compile unit address sized values - case DW_FORM_addr: - form_size = cu->GetAddressByteSize(); - break; - case DW_FORM_ref_addr: - if (cu->GetVersion() <= 2) - form_size = cu->GetAddressByteSize(); - else - form_size = 4; - break; - - // 0 sized form - case DW_FORM_flag_present: - form_size = 0; - break; - - // 1 byte values - case DW_FORM_addrx1: - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - case DW_FORM_strx1: - form_size = 1; - break; - - // 2 byte values - case DW_FORM_addrx2: - case DW_FORM_data2: - case DW_FORM_ref2: - case DW_FORM_strx2: - form_size = 2; - break; - - // 3 byte values - case DW_FORM_addrx3: - case DW_FORM_strx3: - form_size = 3; - break; - - // 4 byte values - case DW_FORM_addrx4: - case DW_FORM_data4: - case DW_FORM_ref4: - case DW_FORM_strx4: - form_size = 4; - break; - - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - case DW_FORM_ref_sig8: - form_size = 8; - break; - - // signed or unsigned LEB 128 values - case DW_FORM_addrx: - case DW_FORM_loclistx: - case DW_FORM_rnglistx: - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - case DW_FORM_GNU_addr_index: - case DW_FORM_GNU_str_index: - case DW_FORM_strx: - data.Skip_LEB128(&offset); - break; - - case DW_FORM_indirect: - form_is_indirect = true; - form = data.GetULEB128(&offset); - break; - - case DW_FORM_strp: - case DW_FORM_sec_offset: - data.GetU32(&offset); - break; - - case DW_FORM_implicit_const: - form_size = 0; - break; - - default: - *offset_ptr = m_offset; - return false; - } - offset += form_size; - - } while (form_is_indirect); - } - } - *offset_ptr = offset; - return true; - } else { + if (m_abbr_idx == 0) { m_tag = llvm::dwarf::DW_TAG_null; m_has_children = false; return true; // NULL debug tag entry } - return false; + lldb::offset_t offset = *offset_ptr; + const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu); + if (abbrevDecl == nullptr) { + cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: invalid abbreviation code %u, please file a bug and " + "attach the file at the start of this error message", + m_offset, (unsigned)abbr_idx); + // WE can't parse anymore if the DWARF is borked... + *offset_ptr = UINT32_MAX; + return false; + } + m_tag = abbrevDecl->Tag(); + m_has_children = abbrevDecl->HasChildren(); + // Skip all data in the .debug_info or .debug_types for the attributes + const uint32_t numAttributes = abbrevDecl->NumAttributes(); + uint32_t i; + dw_form_t form; + for (i = 0; i < numAttributes; ++i) { + form = abbrevDecl->GetFormByIndexUnchecked(i); + llvm::Optional<uint8_t> fixed_skip_size = + DWARFFormValue::GetFixedSize(form, cu); + if (fixed_skip_size) + offset += *fixed_skip_size; + else { + bool form_is_indirect = false; + do { + form_is_indirect = false; + uint32_t form_size = 0; + switch (form) { + // Blocks if inlined data that have a length field and the data bytes + // inlined in the .debug_info/.debug_types + case DW_FORM_exprloc: + case DW_FORM_block: + form_size = data.GetULEB128(&offset); + break; + case DW_FORM_block1: + form_size = data.GetU8_unchecked(&offset); + break; + case DW_FORM_block2: + form_size = data.GetU16_unchecked(&offset); + break; + case DW_FORM_block4: + form_size = data.GetU32_unchecked(&offset); + break; + + // Inlined NULL terminated C-strings + case DW_FORM_string: + data.GetCStr(&offset); + break; + + // Compile unit address sized values + case DW_FORM_addr: + form_size = cu->GetAddressByteSize(); + break; + case DW_FORM_ref_addr: + if (cu->GetVersion() <= 2) + form_size = cu->GetAddressByteSize(); + else + form_size = 4; + break; + + // 0 sized form + case DW_FORM_flag_present: + form_size = 0; + break; + + // 1 byte values + case DW_FORM_addrx1: + case DW_FORM_data1: + case DW_FORM_flag: + case DW_FORM_ref1: + case DW_FORM_strx1: + form_size = 1; + break; + + // 2 byte values + case DW_FORM_addrx2: + case DW_FORM_data2: + case DW_FORM_ref2: + case DW_FORM_strx2: + form_size = 2; + break; + + // 3 byte values + case DW_FORM_addrx3: + case DW_FORM_strx3: + form_size = 3; + break; + + // 4 byte values + case DW_FORM_addrx4: + case DW_FORM_data4: + case DW_FORM_ref4: + case DW_FORM_strx4: + form_size = 4; + break; + + // 8 byte values + case DW_FORM_data8: + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + form_size = 8; + break; + + // signed or unsigned LEB 128 values + case DW_FORM_addrx: + case DW_FORM_loclistx: + case DW_FORM_rnglistx: + case DW_FORM_sdata: + case DW_FORM_udata: + case DW_FORM_ref_udata: + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index: + case DW_FORM_strx: + data.Skip_LEB128(&offset); + break; + + case DW_FORM_indirect: + form_is_indirect = true; + form = data.GetULEB128(&offset); + break; + + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + data.GetU32(&offset); + break; + + case DW_FORM_implicit_const: + form_size = 0; + break; + + default: + cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: Unsupported DW_FORM_0x%x, please file a bug and " + "attach the file at the start of this error message", + m_offset, (unsigned)form); + *offset_ptr = m_offset; + return false; + } + offset += form_size; + + } while (form_is_indirect); + } + } + *offset_ptr = offset; + return true; } static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, @@ -211,11 +214,12 @@ static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit, if (expected_ranges) return std::move(*expected_ranges); unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute, but " + "{0x%8.8x}: DIE has DW_AT_ranges(%s 0x%" PRIx64 ") attribute, but " "range extraction failed (%s), please file a bug " "and attach the file at the start of this error message", - die.GetOffset(), value.Unsigned(), - toString(expected_ranges.takeError()).c_str()); + die.GetOffset(), + llvm::dwarf::FormEncodingString(value.Form()).str().c_str(), + value.Unsigned(), toString(expected_ranges.takeError()).c_str()); return DWARFRangeList(); } @@ -429,7 +433,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(DWARFUnit *cu, } LLVM_FALLTHROUGH; default: - attributes.Append(cu, offset, attr, form); + attributes.Append(form_value, offset, attr); break; } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 0ba56a0a4161..64e86c71ac09 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -35,8 +35,7 @@ public: typedef collection::const_iterator const_iterator; DWARFDebugInfoEntry() - : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), - m_has_children(false), m_abbr_idx(0), m_tag(llvm::dwarf::DW_TAG_null) {} + : m_offset(DW_INVALID_OFFSET), m_sibling_idx(0), m_has_children(false) {} explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } bool operator==(const DWARFDebugInfoEntry &rhs) const; @@ -167,14 +166,14 @@ protected: GetDWARFDeclContextStatic(const DWARFDebugInfoEntry *die, DWARFUnit *cu); dw_offset_t m_offset; // Offset within the .debug_info/.debug_types - uint32_t m_parent_idx; // How many to subtract from "this" to get the parent. - // If zero this die has no parent + uint32_t m_parent_idx = 0; // How many to subtract from "this" to get the + // parent. If zero this die has no parent uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling. // If it is zero, then the DIE doesn't have children, or the // DWARF claimed it had children but the DIE only contained // a single NULL terminating child. m_has_children : 1; - uint16_t m_abbr_idx; + uint16_t m_abbr_idx = 0; /// A copy of the DW_TAG value so we don't have to go through the compile /// unit abbrev table dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 9072b2dc0115..e46694405415 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -23,7 +23,7 @@ class DWARFDeclContext { public: struct Entry { - Entry() : tag(llvm::dwarf::DW_TAG_null), name(nullptr) {} + Entry() = default; Entry(dw_tag_t t, const char *n) : tag(t), name(n) {} bool NameMatches(const Entry &rhs) const { @@ -37,11 +37,11 @@ public: // Test operator explicit operator bool() const { return tag != 0; } - dw_tag_t tag; - const char *name; + dw_tag_t tag = llvm::dwarf::DW_TAG_null; + const char *name = nullptr; }; - DWARFDeclContext() : m_entries(), m_language(lldb::eLanguageTypeUnknown) {} + DWARFDeclContext() : m_entries() {} void AppendDeclContext(dw_tag_t tag, const char *name) { m_entries.push_back(Entry(tag, name)); @@ -83,7 +83,7 @@ protected: typedef std::vector<Entry> collection; collection m_entries; mutable std::string m_qualified_name; - lldb::LanguageType m_language; + lldb::LanguageType m_language = lldb::eLanguageTypeUnknown; }; #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDECLCONTEXT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h index 1b7102cd7e31..2d0d5cad4612 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h @@ -10,7 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEFINES_H #include "lldb/Core/dwarf.h" -#include <stdint.h> +#include <cstdint> namespace lldb_private { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 305f1cbd2826..4c498705da45 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include <assert.h> +#include <cassert> #include "lldb/Core/Module.h" #include "lldb/Core/dwarf.h" @@ -150,40 +150,40 @@ struct FormSize { uint8_t valid:1, size:7; }; static FormSize g_form_sizes[] = { - {0,0}, // 0x00 unused - {0,0}, // 0x01 DW_FORM_addr - {0,0}, // 0x02 unused - {0,0}, // 0x03 DW_FORM_block2 - {0,0}, // 0x04 DW_FORM_block4 - {1,2}, // 0x05 DW_FORM_data2 - {1,4}, // 0x06 DW_FORM_data4 - {1,8}, // 0x07 DW_FORM_data8 - {0,0}, // 0x08 DW_FORM_string - {0,0}, // 0x09 DW_FORM_block - {0,0}, // 0x0a DW_FORM_block1 - {1,1}, // 0x0b DW_FORM_data1 - {1,1}, // 0x0c DW_FORM_flag - {0,0}, // 0x0d DW_FORM_sdata - {1,4}, // 0x0e DW_FORM_strp - {0,0}, // 0x0f DW_FORM_udata - {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - {1,1}, // 0x11 DW_FORM_ref1 - {1,2}, // 0x12 DW_FORM_ref2 - {1,4}, // 0x13 DW_FORM_ref4 - {1,8}, // 0x14 DW_FORM_ref8 - {0,0}, // 0x15 DW_FORM_ref_udata - {0,0}, // 0x16 DW_FORM_indirect - {1,4}, // 0x17 DW_FORM_sec_offset - {0,0}, // 0x18 DW_FORM_exprloc - {1,0}, // 0x19 DW_FORM_flag_present - {0,0}, // 0x1a - {0,0}, // 0x1b - {0,0}, // 0x1c - {0,0}, // 0x1d - {0,0}, // 0x1e - {0,0}, // 0x1f - {1,8}, // 0x20 DW_FORM_ref_sig8 + {0, 0}, // 0x00 unused + {0, 0}, // 0x01 DW_FORM_addr + {0, 0}, // 0x02 unused + {0, 0}, // 0x03 DW_FORM_block2 + {0, 0}, // 0x04 DW_FORM_block4 + {1, 2}, // 0x05 DW_FORM_data2 + {1, 4}, // 0x06 DW_FORM_data4 + {1, 8}, // 0x07 DW_FORM_data8 + {0, 0}, // 0x08 DW_FORM_string + {0, 0}, // 0x09 DW_FORM_block + {0, 0}, // 0x0a DW_FORM_block1 + {1, 1}, // 0x0b DW_FORM_data1 + {1, 1}, // 0x0c DW_FORM_flag + {0, 0}, // 0x0d DW_FORM_sdata + {1, 4}, // 0x0e DW_FORM_strp + {0, 0}, // 0x0f DW_FORM_udata + {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes + // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later + {1, 1}, // 0x11 DW_FORM_ref1 + {1, 2}, // 0x12 DW_FORM_ref2 + {1, 4}, // 0x13 DW_FORM_ref4 + {1, 8}, // 0x14 DW_FORM_ref8 + {0, 0}, // 0x15 DW_FORM_ref_udata + {0, 0}, // 0x16 DW_FORM_indirect + {1, 4}, // 0x17 DW_FORM_sec_offset + {0, 0}, // 0x18 DW_FORM_exprloc + {1, 0}, // 0x19 DW_FORM_flag_present + {0, 0}, // 0x1a DW_FORM_strx (ULEB128) + {0, 0}, // 0x1b DW_FORM_addrx (ULEB128) + {1, 4}, // 0x1c DW_FORM_ref_sup4 + {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64) + {1, 16}, // 0x1e DW_FORM_data16 + {1, 4}, // 0x1f DW_FORM_line_strp + {1, 8}, // 0x20 DW_FORM_ref_sig8 }; llvm::Optional<uint8_t> @@ -286,6 +286,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: case DW_FORM_strp: + case DW_FORM_line_strp: *offset_ptr += 4; return true; @@ -398,7 +399,8 @@ void DWARFFormValue::Dump(Stream &s) const { case DW_FORM_udata: s.PutULEB128(uvalue); break; - case DW_FORM_strp: { + case DW_FORM_strp: + case DW_FORM_line_strp: { const char *dbg_str = AsCString(); if (dbg_str) { s.QuotedCString(dbg_str); @@ -606,6 +608,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) { case DW_FORM_flag: case DW_FORM_sdata: case DW_FORM_strp: + case DW_FORM_line_strp: case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2: diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index fe6a55520978..9406bcf0c038 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -10,8 +10,8 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFFORMVALUE_H #include "DWARFDataExtractor.h" -#include <stddef.h> #include "llvm/ADT/Optional.h" +#include <cstddef> class DWARFUnit; class SymbolFileDWARF; @@ -20,14 +20,14 @@ class DWARFDIE; class DWARFFormValue { public: typedef struct ValueTypeTag { - ValueTypeTag() : value(), data(nullptr) { value.uval = 0; } + ValueTypeTag() : value() { value.uval = 0; } union { uint64_t uval; int64_t sval; const char *cstr; } value; - const uint8_t *data; + const uint8_t *data = nullptr; } ValueType; enum { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index a761dd3daac4..824e43872269 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -236,6 +236,11 @@ void DWARFUnit::ExtractDIEsRWLocked() { } if (!m_die_array.empty()) { + // The last die cannot have children (if it did, it wouldn't be the last one). + // This only makes a difference for malformed dwarf that does not have a + // terminating null die. + m_die_array.back().SetHasChildren(false); + if (m_first_die) { // Only needed for the assertion. m_first_die.SetHasChildren(m_die_array.front().HasChildren()); @@ -292,8 +297,7 @@ uint64_t DWARFUnit::GetDWOId() { // m_die_array_mutex must be already held as read/write. void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { - llvm::Optional<uint64_t> addr_base, gnu_addr_base, ranges_base, - gnu_ranges_base; + llvm::Optional<uint64_t> addr_base, gnu_addr_base, gnu_ranges_base; DWARFAttributes attributes; size_t num_attributes = cu_die.GetAttributes(this, attributes); @@ -320,8 +324,7 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { SetLoclistsBase(form_value.Unsigned()); break; case DW_AT_rnglists_base: - ranges_base = form_value.Unsigned(); - SetRangesBase(*ranges_base); + SetRangesBase(form_value.Unsigned()); break; case DW_AT_str_offsets_base: SetStrOffsetsBase(form_value.Unsigned()); @@ -482,19 +485,46 @@ DWARFDataExtractor DWARFUnit::GetLocationData() const { } void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { + lldbassert(!m_rnglist_table_done); + m_ranges_base = ranges_base; +} - if (GetVersion() < 5) - return; +const llvm::Optional<llvm::DWARFDebugRnglistTable> & +DWARFUnit::GetRnglistTable() { + if (GetVersion() >= 5 && !m_rnglist_table_done) { + m_rnglist_table_done = true; + if (auto table_or_error = + ParseListTableHeader<llvm::DWARFDebugRnglistTable>( + m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), + m_ranges_base, DWARF32)) + m_rnglist_table = std::move(table_or_error.get()); + else + GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( + "Failed to extract range list table at offset 0x%" PRIx64 ": %s", + m_ranges_base, toString(table_or_error.takeError()).c_str()); + } + return m_rnglist_table; +} - if (auto table_or_error = ParseListTableHeader<llvm::DWARFDebugRnglistTable>( - m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), - ranges_base, DWARF32)) - m_rnglist_table = std::move(table_or_error.get()); - else - GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( - "Failed to extract range list table at offset 0x%" PRIx64 ": %s", - ranges_base, toString(table_or_error.takeError()).c_str()); +// This function is called only for DW_FORM_rnglistx. +llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) { + if (!GetRnglistTable()) + return llvm::createStringError(errc::invalid_argument, + "missing or invalid range list table"); + if (!m_ranges_base) + return llvm::createStringError(errc::invalid_argument, + "DW_FORM_rnglistx cannot be used without " + "DW_AT_rnglists_base for CU at 0x%8.8x", + GetOffset()); + if (llvm::Optional<uint64_t> off = GetRnglistTable()->getOffsetEntry( + m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), Index)) + return *off + m_ranges_base; + return llvm::createStringError( + errc::invalid_argument, + "invalid range list table index %u; OffsetEntryCount is %u, " + "DW_AT_rnglists_base is %" PRIu64, + Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base); } void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { @@ -784,12 +814,11 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { llvm::Expected<DWARFUnitHeader> DWARFUnitHeader::extract(const DWARFDataExtractor &data, - DIERef::Section section, lldb::offset_t *offset_ptr, - const llvm::DWARFUnitIndex *index) { + DIERef::Section section, + lldb_private::DWARFContext &context, + lldb::offset_t *offset_ptr) { DWARFUnitHeader header; header.m_offset = *offset_ptr; - if (index) - header.m_index_entry = index->getFromOffset(*offset_ptr); header.m_length = data.GetDWARFInitialLength(offset_ptr); header.m_version = data.GetU16(offset_ptr); if (header.m_version == 5) { @@ -806,6 +835,16 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; } + if (context.isDwo()) { + if (header.IsTypeUnit()) { + header.m_index_entry = + context.GetAsLLVM().getTUIndex().getFromOffset(header.m_offset); + } else { + header.m_index_entry = + context.GetAsLLVM().getCUIndex().getFromOffset(header.m_offset); + } + } + if (header.m_index_entry) { if (header.m_abbr_offset) { return llvm::createStringError( @@ -856,12 +895,11 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, llvm::Expected<DWARFUnitSP> DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, const DWARFDataExtractor &debug_info, - DIERef::Section section, lldb::offset_t *offset_ptr, - const llvm::DWARFUnitIndex *index) { + DIERef::Section section, lldb::offset_t *offset_ptr) { assert(debug_info.ValidOffset(*offset_ptr)); - auto expected_header = - DWARFUnitHeader::extract(debug_info, section, offset_ptr, index); + auto expected_header = DWARFUnitHeader::extract( + debug_info, section, dwarf.GetDWARFContext(), offset_ptr); if (!expected_header) return expected_header.takeError(); @@ -930,11 +968,11 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { return ranges; } - if (!m_rnglist_table) + if (!GetRnglistTable()) return llvm::createStringError(errc::invalid_argument, "missing or invalid range list table"); - auto range_list_or_error = m_rnglist_table->findList( + auto range_list_or_error = GetRnglistTable()->findList( m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset); if (!range_list_or_error) return range_list_or_error.takeError(); @@ -963,12 +1001,8 @@ DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromIndex(uint32_t index) { - if (llvm::Optional<uint64_t> offset = GetRnglistOffset(index)) - return FindRnglistFromOffset(*offset); - if (m_rnglist_table) - return llvm::createStringError(errc::invalid_argument, - "invalid range list table index %d", index); - - return llvm::createStringError(errc::invalid_argument, - "missing or invalid range list table"); + llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index); + if (!maybe_offset) + return maybe_offset.takeError(); + return FindRnglistFromOffset(*maybe_offset); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index 5739c36bbacb..da79a6aaf64e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -73,7 +73,8 @@ public: static llvm::Expected<DWARFUnitHeader> extract(const lldb_private::DWARFDataExtractor &data, DIERef::Section section, - lldb::offset_t *offset_ptr, const llvm::DWARFUnitIndex *index); + lldb_private::DWARFContext &dwarf_context, + lldb::offset_t *offset_ptr); }; class DWARFUnit : public lldb_private::UserID { @@ -84,8 +85,7 @@ public: static llvm::Expected<DWARFUnitSP> extract(SymbolFileDWARF &dwarf2Data, lldb::user_id_t uid, const lldb_private::DWARFDataExtractor &debug_info, - DIERef::Section section, lldb::offset_t *offset_ptr, - const llvm::DWARFUnitIndex *index); + DIERef::Section section, lldb::offset_t *offset_ptr); virtual ~DWARFUnit(); bool IsDWOUnit() { return m_is_dwo; } @@ -235,15 +235,7 @@ public: /// Return a rangelist's offset based on an index. The index designates /// an entry in the rangelist table's offset array and is supplied by /// DW_FORM_rnglistx. - llvm::Optional<uint64_t> GetRnglistOffset(uint32_t Index) const { - if (!m_rnglist_table) - return llvm::None; - if (llvm::Optional<uint64_t> off = m_rnglist_table->getOffsetEntry( - m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), - Index)) - return *off + m_ranges_base; - return llvm::None; - } + llvm::Expected<uint64_t> GetRnglistOffset(uint32_t Index); llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) { if (!m_loclist_table_header) @@ -291,6 +283,8 @@ protected: return &m_die_array[0]; } + const llvm::Optional<llvm::DWARFDebugRnglistTable> &GetRnglistTable(); + SymbolFileDWARF &m_dwarf; std::shared_ptr<DWARFUnit> m_dwo; DWARFUnitHeader m_header; @@ -331,6 +325,7 @@ protected: dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base. llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table; + bool m_rnglist_table_done = false; llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header; const DIERef::Section m_section; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index d36f2a8bccf7..ce71281db8bd 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -130,8 +130,7 @@ DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f, : die_offset(o), tag(t), type_flags(f), qualified_name_hash(h) {} DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset) - : die_base_offset(_die_base_offset), atoms(), atom_mask(0), - min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) { + : die_base_offset(_die_base_offset), atoms() { // Define an array of DIE offsets by first defining an array, and then define // the atom type for the array, in this case we have an array of DIE offsets. AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index ad178fc6a987..efc08e47a280 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -101,9 +101,9 @@ public: /// DIE offset base so die offsets in hash_data can be CU relative. dw_offset_t die_base_offset; AtomArray atoms; - uint32_t atom_mask; - size_t min_hash_data_byte_size; - bool hash_data_has_fixed_byte_size; + uint32_t atom_mask = 0; + size_t min_hash_data_byte_size = 0; + bool hash_data_has_fixed_byte_size = true; }; class Header : public MappedHash::Header<Prologue> { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index dda599baffeb..1f40d880ea34 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -13,9 +13,11 @@ #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" #include "lldb/Core/Module.h" +#include "lldb/Core/Progress.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ThreadPool.h" using namespace lldb_private; @@ -56,6 +58,17 @@ void ManualDWARFIndex::Index() { if (units_to_index.empty()) return; + StreamString module_desc; + m_module.GetDescription(module_desc.AsRawOstream(), + lldb::eDescriptionLevelBrief); + + // Include 2 passes per unit to index for extracting DIEs from the unit and + // indexing the unit, and then 8 extra entries for finalizing each index set. + const uint64_t total_progress = units_to_index.size() * 2 + 8; + Progress progress( + llvm::formatv("Manually indexing DWARF for {0}", module_desc.GetData()), + total_progress); + std::vector<IndexSet> sets(units_to_index.size()); // Keep memory down by clearing DIEs for any units if indexing @@ -64,10 +77,12 @@ void ManualDWARFIndex::Index() { units_to_index.size()); auto parser_fn = [&](size_t cu_idx) { IndexUnit(*units_to_index[cu_idx], dwp_dwarf, sets[cu_idx]); + progress.Increment(); }; - auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) { + auto extract_fn = [&](size_t cu_idx) { clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped(); + progress.Increment(); }; // Share one thread pool across operations to avoid the overhead of @@ -92,11 +107,12 @@ void ManualDWARFIndex::Index() { pool.async(parser_fn, i); pool.wait(); - auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) { + auto finalize_fn = [this, &sets, &progress](NameToDIE(IndexSet::*index)) { NameToDIE &result = m_set.*index; for (auto &set : sets) result.Append(set.*index); result.Finalize(); + progress.Increment(); }; pool.async(finalize_fn, &IndexSet::function_basenames); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index 5aa841cf3d10..a6863f6c9549 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -22,7 +22,7 @@ class NameToDIE { public: NameToDIE() : m_map() {} - ~NameToDIE() {} + ~NameToDIE() = default; void Dump(lldb_private::Stream *s); diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 3656c7333f27..ccaf31317d75 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" @@ -74,18 +75,19 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" #include <algorithm> #include <map> #include <memory> -#include <ctype.h> -#include <string.h> +#include <cctype> +#include <cstring> //#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF -#include <stdio.h> +#include <cstdio> #define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) #else #define DEBUG_PRINTF(fmt, ...) @@ -238,9 +240,12 @@ ParseSupportFilesFromPrologue(const lldb::ModuleSP &module, const size_t number_of_files = prologue.FileNames.size(); for (size_t idx = first_file; idx <= number_of_files; ++idx) { std::string remapped_file; - if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) - if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file)) + if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style)) { + if (auto remapped = module->RemapSourceFile(llvm::StringRef(*file_path))) + remapped_file = *remapped; + else remapped_file = std::move(*file_path); + } // Unconditionally add an entry, so the indices match up. support_files.EmplaceBack(remapped_file, style); @@ -358,8 +363,7 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset, } } - for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { GetTypes(child_die, min_die_offset, max_die_offset, type_mask, type_set); } } @@ -435,7 +439,7 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFileSP objfile_sp, m_fetched_external_modules(false), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} -SymbolFileDWARF::~SymbolFileDWARF() {} +SymbolFileDWARF::~SymbolFileDWARF() = default; static ConstString GetDWARFMachOSegmentName() { static ConstString g_dwarf_section_name("__DWARF"); @@ -467,22 +471,32 @@ void SymbolFileDWARF::InitializeObject() { Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) { + StreamString module_desc; + GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(), + lldb::eDescriptionLevelBrief); DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc; LoadSectionData(eSectionTypeDWARFAppleNames, apple_names); LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces); LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types); LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc); - m_index = AppleDWARFIndex::Create( - *GetObjectFile()->GetModule(), apple_names, apple_namespaces, - apple_types, apple_objc, m_context.getOrLoadStrData()); + if (apple_names.GetByteSize() > 0 || apple_namespaces.GetByteSize() > 0 || + apple_types.GetByteSize() > 0 || apple_objc.GetByteSize() > 0) { + Progress progress(llvm::formatv("Loading Apple DWARF index for {0}", + module_desc.GetData())); + m_index = AppleDWARFIndex::Create( + *GetObjectFile()->GetModule(), apple_names, apple_namespaces, + apple_types, apple_objc, m_context.getOrLoadStrData()); - if (m_index) - return; + if (m_index) + return; + } DWARFDataExtractor debug_names; LoadSectionData(eSectionTypeDWARFDebugNames, debug_names); if (debug_names.GetByteSize() > 0) { + Progress progress( + llvm::formatv("Loading DWARF5 index for {0}", module_desc.GetData())); llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or = DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(), debug_names, @@ -669,9 +683,8 @@ static void MakeAbsoluteAndRemap(FileSpec &file_spec, DWARFUnit &dwarf_cu, // files are NFS mounted. file_spec.MakeAbsolute(dwarf_cu.GetCompilationDirectory()); - std::string remapped_file; - if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file)) - file_spec.SetFile(remapped_file, FileSpec::Style::native); + if (auto remapped_file = module_sp->RemapSourceFile(file_spec.GetPath())) + file_spec.SetFile(*remapped_file, FileSpec::Style::native); } lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) { @@ -973,8 +986,7 @@ bool SymbolFileDWARF::ParseImportedModules( if (!die) return false; - for (DWARFDIE child_die = die.GetFirstChild(); child_die; - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { if (child_die.Tag() != DW_TAG_imported_declaration) continue; @@ -1233,8 +1245,7 @@ size_t SymbolFileDWARF::ParseBlocksRecursive( bool SymbolFileDWARF::ClassOrStructIsVirtual(const DWARFDIE &parent_die) { if (parent_die) { - for (DWARFDIE die = parent_die.GetFirstChild(); die; - die = die.GetSibling()) { + for (DWARFDIE die : parent_die.children()) { dw_tag_t tag = die.Tag(); bool check_virtuality = false; switch (tag) { @@ -1639,6 +1650,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( return nullptr; dwo_file.SetFile(comp_dir, FileSpec::Style::native); + if (dwo_file.IsRelative()) { + // if DW_AT_comp_dir is relative, it should be relative to the location + // of the executable, not to the location from which the debugger was + // launched. + dwo_file.PrependPathComponent( + m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef()); + } FileSystem::Instance().Resolve(dwo_file); dwo_file.AppendPathComponent(dwo_name); } @@ -1784,7 +1802,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() { if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr, nullptr, location_result, &error)) { if (location_result.GetValueType() == - Value::eValueTypeFileAddress) { + Value::ValueType::FileAddress) { lldb::addr_t file_addr = location_result.GetScalar().ULongLong(); lldb::addr_t byte_size = 1; @@ -1850,17 +1868,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); DWARFDebugInfo &debug_info = DebugInfo(); - llvm::Expected<DWARFDebugAranges &> aranges = - debug_info.GetCompileUnitAranges(); - if (!aranges) { - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); - LLDB_LOG_ERROR(log, aranges.takeError(), - "SymbolFileDWARF::ResolveSymbolContext failed to get cu " - "aranges. {0}"); - return 0; - } - - const dw_offset_t cu_offset = aranges->FindAddress(file_vm_addr); + const DWARFDebugAranges &aranges = debug_info.GetCompileUnitAranges(); + const dw_offset_t cu_offset = aranges.FindAddress(file_vm_addr); if (cu_offset == DW_INVALID_OFFSET) { // Global variables are not in the compile unit address ranges. The only // way to currently find global variables is to iterate over the @@ -1949,12 +1958,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr, return resolved; } -uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, - uint32_t line, - bool check_inlines, - SymbolContextItem resolve_scope, - SymbolContextList &sc_list) { +uint32_t SymbolFileDWARF::ResolveSymbolContext( + const SourceLocationSpec &src_location_spec, + SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + const bool check_inlines = src_location_spec.GetCheckInlines(); const uint32_t prev_size = sc_list.GetSize(); if (resolve_scope & eSymbolContextCompUnit) { for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; @@ -1963,69 +1971,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, if (!dc_cu) continue; - bool file_spec_matches_cu_file_spec = - FileSpec::Match(file_spec, dc_cu->GetPrimaryFile()); + bool file_spec_matches_cu_file_spec = FileSpec::Match( + src_location_spec.GetFileSpec(), dc_cu->GetPrimaryFile()); if (check_inlines || file_spec_matches_cu_file_spec) { - SymbolContext sc(m_objfile_sp->GetModule()); - sc.comp_unit = dc_cu; - uint32_t file_idx = UINT32_MAX; - - // If we are looking for inline functions only and we don't find it - // in the support files, we are done. - if (check_inlines) { - file_idx = - sc.comp_unit->GetSupportFiles().FindFileIndex(1, file_spec, true); - if (file_idx == UINT32_MAX) - continue; - } - - if (line != 0) { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table != nullptr && line != 0) { - // We will have already looked up the file index if we are - // searching for inline entries. - if (!check_inlines) - file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex( - 1, file_spec, true); - - if (file_idx != UINT32_MAX) { - uint32_t found_line; - uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex( - 0, file_idx, line, false, &sc.line_entry); - found_line = sc.line_entry.line; - - while (line_idx != UINT32_MAX) { - sc.function = nullptr; - sc.block = nullptr; - if (resolve_scope & - (eSymbolContextFunction | eSymbolContextBlock)) { - const lldb::addr_t file_vm_addr = - sc.line_entry.range.GetBaseAddress().GetFileAddress(); - if (file_vm_addr != LLDB_INVALID_ADDRESS) { - ResolveFunctionAndBlock( - file_vm_addr, resolve_scope & eSymbolContextBlock, sc); - } - } - - sc_list.Append(sc); - line_idx = line_table->FindLineEntryIndexByFileIndex( - line_idx + 1, file_idx, found_line, true, &sc.line_entry); - } - } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit - sc_list.Append(sc); - } - } else if (file_spec_matches_cu_file_spec && !check_inlines) { - // only append the context if we aren't looking for inline call - // sites by file and line and if the file spec matches that of - // the compile unit - sc_list.Append(sc); - } - + dc_cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); if (!check_inlines) break; } @@ -2462,7 +2411,7 @@ void SymbolFileDWARF::FindTypes( return; m_index->GetTypes(name, [&](DWARFDIE die) { - if (!languages[GetLanguage(*die.GetCU())]) + if (!languages[GetLanguageFamily(*die.GetCU())]) return true; llvm::SmallVector<CompilerContext, 4> die_context; @@ -3126,8 +3075,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, continue; switch (attr) { case DW_AT_decl_file: - decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex( - form_value.Unsigned())); + decl.SetFile( + attributes.CompileUnitAtIndex(i)->GetFile(form_value.Unsigned())); break; case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); @@ -3469,8 +3418,7 @@ SymbolFileDWARF::FindBlockContainingSpecification( // Give the concrete function die specified by "func_die_offset", find the // concrete block whose DW_AT_specification or DW_AT_abstract_origin points // to "spec_block_die_offset" - for (DWARFDIE child_die = die.GetFirstChild(); child_die; - child_die = child_die.GetSibling()) { + for (DWARFDIE child_die : die.children()) { DWARFDIE result_die = FindBlockContainingSpecification(child_die, spec_block_die_offset); if (result_die) @@ -3599,8 +3547,7 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc, static CallSiteParameterArray CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) { CallSiteParameterArray parameters; - for (DWARFDIE child = call_site_die.GetFirstChild(); child.IsValid(); - child = child.GetSibling()) { + for (DWARFDIE child : call_site_die.children()) { if (child.Tag() != DW_TAG_call_site_parameter && child.Tag() != DW_TAG_GNU_call_site_parameter) continue; @@ -3665,8 +3612,7 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) { // For now, assume that all entries are nested directly under the subprogram // (this is the kind of DWARF LLVM produces) and parse them eagerly. std::vector<std::unique_ptr<CallEdge>> call_edges; - for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid(); - child = child.GetSibling()) { + for (DWARFDIE child : function_die.children()) { if (child.Tag() != DW_TAG_call_site && child.Tag() != DW_TAG_GNU_call_site) continue; @@ -3842,7 +3788,7 @@ void SymbolFileDWARF::DumpClangAST(Stream &s) { } SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() { - if (m_debug_map_symfile == nullptr && !m_debug_map_module_wp.expired()) { + if (m_debug_map_symfile == nullptr) { lldb::ModuleSP module_sp(m_debug_map_module_wp.lock()); if (module_sp) { m_debug_map_symfile = @@ -3936,3 +3882,10 @@ LanguageType SymbolFileDWARF::LanguageTypeFromDWARF(uint64_t val) { LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) { return LanguageTypeFromDWARF(unit.GetDWARFLanguageType()); } + +LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) { + auto lang = (llvm::dwarf::SourceLanguage)unit.GetDWARFLanguageType(); + if (llvm::dwarf::isCPlusPlus(lang)) + lang = DW_LANG_C_plus_plus; + return LanguageTypeFromDWARF(lang); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 019f76c67c63..d9feeef549ed 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -161,11 +161,10 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, @@ -318,6 +317,8 @@ public: static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val); static lldb::LanguageType GetLanguage(DWARFUnit &unit); + /// Same as GetLanguage() but reports all C++ versions as C++ (no version). + static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit); protected: typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index fa24f975b073..4e2e5e16637b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -16,7 +16,6 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/RegularExpression.h" -#include "lldb/Utility/Timer.h" //#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT #if defined(DEBUG_OSO_DMAP) @@ -34,6 +33,9 @@ #include "LogChannelDWARF.h" #include "SymbolFileDWARF.h" +// Work around the fact that Timer.h pulls in the system Mach-O headers. +#include "lldb/Utility/Timer.h" + #include <memory> using namespace lldb; @@ -246,7 +248,7 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap(ObjectFileSP objfile_sp) m_func_indexes(), m_glob_indexes(), m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {} -SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() {} +SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap() = default; void SymbolFileDWARFDebugMap::InitializeObject() {} @@ -806,7 +808,7 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr, } uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const uint32_t initial = sc_list.GetSize(); @@ -815,18 +817,19 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext( for (uint32_t i = 0; i < cu_count; ++i) { // If we are checking for inlines, then we need to look through all compile // units no matter if "file_spec" matches. - bool resolve = check_inlines; + bool resolve = src_location_spec.GetCheckInlines(); if (!resolve) { FileSpec so_file_spec; if (GetFileSpecForSO(i, so_file_spec)) - resolve = FileSpec::Match(file_spec, so_file_spec); + resolve = + FileSpec::Match(src_location_spec.GetFileSpec(), so_file_spec); } if (resolve) { SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i); if (oso_dwarf) - oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines, - resolve_scope, sc_list); + oso_dwarf->ResolveSymbolContext(src_location_spec, resolve_scope, + sc_list); } } return sc_list.GetSize() - initial; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 06f0d48c04ca..8b6624e70869 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -97,11 +97,10 @@ public: uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr, lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, const lldb_private::CompilerDeclContext &parent_decl_ctx, @@ -171,18 +170,17 @@ protected: llvm::sys::TimePoint<> oso_mod_time; OSOInfoSP oso_sp; lldb::CompUnitSP compile_unit_sp; - uint32_t first_symbol_index; - uint32_t last_symbol_index; - uint32_t first_symbol_id; - uint32_t last_symbol_id; + uint32_t first_symbol_index = UINT32_MAX; + uint32_t last_symbol_index = UINT32_MAX; + uint32_t first_symbol_id = UINT32_MAX; + uint32_t last_symbol_id = UINT32_MAX; FileRangeMap file_range_map; - bool file_range_map_valid; + bool file_range_map_valid = false; CompileUnitInfo() : so_file(), oso_path(), oso_mod_time(), oso_sp(), compile_unit_sp(), - first_symbol_index(UINT32_MAX), last_symbol_index(UINT32_MAX), - first_symbol_id(UINT32_MAX), last_symbol_id(UINT32_MAX), - file_range_map(), file_range_map_valid(false) {} + + file_range_map() {} const FileRangeMap &GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile); }; @@ -280,8 +278,7 @@ protected: // OSOEntry class OSOEntry { public: - OSOEntry() - : m_exe_sym_idx(UINT32_MAX), m_oso_file_addr(LLDB_INVALID_ADDRESS) {} + OSOEntry() = default; OSOEntry(uint32_t exe_sym_idx, lldb::addr_t oso_file_addr) : m_exe_sym_idx(exe_sym_idx), m_oso_file_addr(oso_file_addr) {} @@ -299,8 +296,8 @@ protected: } protected: - uint32_t m_exe_sym_idx; - lldb::addr_t m_oso_file_addr; + uint32_t m_exe_sym_idx = UINT32_MAX; + lldb::addr_t m_oso_file_addr = LLDB_INVALID_ADDRESS; }; typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 2181989cd37a..34ff23667465 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -8,7 +8,7 @@ #include "UniqueDWARFASTType.h" -#include "lldb/Symbol/Declaration.h" +#include "lldb/Core/Declaration.h" bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die, const lldb_private::Declaration &decl, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index a1b1a3009787..0947d1e581c5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -14,16 +14,12 @@ #include "llvm/ADT/DenseMap.h" #include "DWARFDIE.h" -#include "lldb/Symbol/Declaration.h" +#include "lldb/Core/Declaration.h" class UniqueDWARFASTType { public: // Constructors and Destructors - UniqueDWARFASTType() - : m_type_sp(), m_die(), m_declaration(), - m_byte_size( - -1) // Set to negative value to make sure we have a valid value - {} + UniqueDWARFASTType() : m_type_sp(), m_die(), m_declaration() {} UniqueDWARFASTType(lldb::TypeSP &type_sp, const DWARFDIE &die, const lldb_private::Declaration &decl, int32_t byte_size) @@ -34,7 +30,7 @@ public: : m_type_sp(rhs.m_type_sp), m_die(rhs.m_die), m_declaration(rhs.m_declaration), m_byte_size(rhs.m_byte_size) {} - ~UniqueDWARFASTType() {} + ~UniqueDWARFASTType() = default; UniqueDWARFASTType &operator=(const UniqueDWARFASTType &rhs) { if (this != &rhs) { @@ -49,14 +45,14 @@ public: lldb::TypeSP m_type_sp; DWARFDIE m_die; lldb_private::Declaration m_declaration; - int32_t m_byte_size; + int32_t m_byte_size = -1; }; class UniqueDWARFASTTypeList { public: UniqueDWARFASTTypeList() : m_collection() {} - ~UniqueDWARFASTTypeList() {} + ~UniqueDWARFASTTypeList() = default; uint32_t GetSize() { return (uint32_t)m_collection.size(); } @@ -76,7 +72,7 @@ class UniqueDWARFASTTypeMap { public: UniqueDWARFASTTypeMap() : m_collection() {} - ~UniqueDWARFASTTypeMap() {} + ~UniqueDWARFASTTypeMap() = default; void Insert(lldb_private::ConstString name, const UniqueDWARFASTType &entry) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp index f25dc84fb342..9f09c0accc87 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp @@ -43,7 +43,7 @@ static bool IsMainFile(llvm::StringRef main, llvm::StringRef other) { llvm::SmallString<64> normalized(other); llvm::sys::path::native(normalized); - return main.equals_lower(normalized); + return main.equals_insensitive(normalized); } static void ParseCompile3(const CVSymbol &sym, CompilandIndexItem &cci) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 5b4ab78ac219..43cf262016c2 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1093,7 +1093,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, } if (!params.empty()) - m_clang.SetFunctionParameters(&function_decl, params.data(), params.size()); + m_clang.SetFunctionParameters(&function_decl, params); } clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp index ecae767e4469..4f570d5e6788 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp @@ -41,7 +41,7 @@ static uint32_t ResolveLLDBRegisterNum(llvm::StringRef reg_name, llvm::Triple::A auto it = llvm::find_if( register_names, [®_name](const llvm::EnumEntry<uint16_t> ®ister_entry) { - return reg_name.compare_lower(register_entry.Name) == 0; + return reg_name.compare_insensitive(register_entry.Name) == 0; }); if (it == register_names.end()) diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 24b4c64a91bc..b9b075d83b6a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -256,7 +256,7 @@ SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) { SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp) : SymbolFile(std::move(objfile_sp)) {} -SymbolFileNativePDB::~SymbolFileNativePDB() {} +SymbolFileNativePDB::~SymbolFileNativePDB() = default; uint32_t SymbolFileNativePDB::CalculateAbilities() { uint32_t abilities = 0; @@ -1001,7 +1001,7 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( } uint32_t SymbolFileNativePDB::ResolveSymbolContext( - const FileSpec &file_spec, uint32_t line, bool check_inlines, + const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { return 0; } @@ -1039,7 +1039,7 @@ static void TerminateLineSequence(LineTable &table, table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize, last_line, 0, file_number, false, false, false, false, true); - table.InsertSequence(seq.release()); + table.InsertSequence(seq.get()); } bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index 61c1d77164b7..def0995065ca 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -120,8 +120,7 @@ public: uint32_t ResolveSymbolContext(const Address &so_addr, lldb::SymbolContextItem resolve_scope, SymbolContext &sc) override; - uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line, - bool check_inlines, + uint32_t ResolveSymbolContext(const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) override; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index f9c12e634140..78a0d09a681a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -17,8 +17,8 @@ #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" +#include "lldb/Core/Declaration.h" #include "lldb/Core/Module.h" -#include "lldb/Symbol/Declaration.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" @@ -326,7 +326,7 @@ GetDeclFromContextByName(const clang::ASTContext &ast, if (result.empty()) return nullptr; - return result[0]; + return *result.begin(); } static bool IsAnonymousNamespaceName(llvm::StringRef name) { @@ -355,7 +355,7 @@ static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) { PDBASTParser::PDBASTParser(lldb_private::TypeSystemClang &ast) : m_ast(ast) {} -PDBASTParser::~PDBASTParser() {} +PDBASTParser::~PDBASTParser() = default; // DebugInfoASTParser interface @@ -534,8 +534,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type); assert(type_def); + SymbolFile *symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + lldb_private::Type *target_type = - m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId()); + symbol_file->ResolveTypeUID(type_def->getTypeId()); if (!target_type) return nullptr; @@ -609,8 +613,13 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { auto arg = arg_enum->getChildAtIndex(arg_idx); if (!arg) break; + + SymbolFile *symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + lldb_private::Type *arg_type = - m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId()); + symbol_file->ResolveTypeUID(arg->getSymIndexId()); // If there's some error looking up one of the dependent types of this // function signature, bail. if (!arg_type) @@ -621,8 +630,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { lldbassert(arg_list.size() <= num_args); auto pdb_return_type = func_sig->getReturnType(); + SymbolFile *symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + lldb_private::Type *return_type = - m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId()); + symbol_file->ResolveTypeUID(pdb_return_type->getSymIndexId()); // If there's some error looking up one of the dependent types of this // function signature, bail. if (!return_type) @@ -654,10 +667,13 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (uint64_t size = array_type->getLength()) bytes = size; + SymbolFile *symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + // If array rank > 0, PDB gives the element type at N=0. So element type // will parsed in the order N=0, N=1,..., N=rank sequentially. - lldb_private::Type *element_type = - m_ast.GetSymbolFile()->ResolveTypeUID(element_uid); + lldb_private::Type *element_type = symbol_file->ResolveTypeUID(element_uid); if (!element_type) return nullptr; @@ -711,7 +727,12 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { case PDB_SymType::PointerType: { auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type); assert(pointer_type); - Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID( + + SymbolFile *symbol_file = m_ast.GetSymbolFile(); + if (!symbol_file) + return nullptr; + + Type *pointee_type = symbol_file->ResolveTypeUID( pointer_type->getPointeeType()->getSymIndexId()); if (!pointee_type) return nullptr; @@ -719,8 +740,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { if (pointer_type->isPointerToDataMember() || pointer_type->isPointerToMemberFunction()) { auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId(); - auto class_parent_type = - m_ast.GetSymbolFile()->ResolveTypeUID(class_parent_uid); + auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_uid); assert(class_parent_type); CompilerType pointer_ast_type; @@ -950,7 +970,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { } } if (params.size()) - m_ast.SetFunctionParameters(decl, params.data(), params.size()); + m_ast.SetFunctionParameters(decl, params); m_uid_to_decl[sym_id] = decl; diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index befc08158cea..6b30ad26dca7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -84,8 +84,10 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line, static bool ShouldUseNativeReader() { #if defined(_WIN32) llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER"); - return use_native.equals_lower("on") || use_native.equals_lower("yes") || - use_native.equals_lower("1") || use_native.equals_lower("true"); + return use_native.equals_insensitive("on") || + use_native.equals_insensitive("yes") || + use_native.equals_insensitive("1") || + use_native.equals_insensitive("true"); #else return true; #endif @@ -128,7 +130,7 @@ SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) { SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp) : SymbolFile(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {} -SymbolFilePDB::~SymbolFilePDB() {} +SymbolFilePDB::~SymbolFilePDB() = default; uint32_t SymbolFilePDB::CalculateAbilities() { uint32_t abilities = 0; @@ -784,10 +786,12 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, } uint32_t SymbolFilePDB::ResolveSymbolContext( - const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, + const lldb_private::SourceLocationSpec &src_location_spec, SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); const size_t old_size = sc_list.GetSize(); + const FileSpec &file_spec = src_location_spec.GetFileSpec(); + const uint32_t line = src_location_spec.GetLine().getValueOr(0); if (resolve_scope & lldb::eSymbolContextCompUnit) { // Locate all compilation units with line numbers referencing the specified // file. For example, if `file_spec` is <vector>, then this should return @@ -806,7 +810,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext( // this file unless the FileSpec matches. For inline functions, we don't // have to match the FileSpec since they could be defined in headers // other than file specified in FileSpec. - if (!check_inlines) { + if (!src_location_spec.GetCheckInlines()) { std::string source_file = compiland->getSourceFileFullPath(); if (source_file.empty()) continue; @@ -1813,7 +1817,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit, sequence.get(), prev_addr + prev_length, prev_line, 0, prev_source_idx, false, false, false, false, true); - line_table->InsertSequence(sequence.release()); + line_table->InsertSequence(sequence.get()); sequence = line_table->CreateLineSequenceContainer(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 928cbffc5f63..2171b7f686cc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -104,11 +104,10 @@ public: lldb::SymbolContextItem resolve_scope, lldb_private::SymbolContext &sc) override; - uint32_t - ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, - bool check_inlines, - lldb::SymbolContextItem resolve_scope, - lldb_private::SymbolContextList &sc_list) override; + uint32_t ResolveSymbolContext( + const lldb_private::SourceLocationSpec &src_location_spec, + lldb::SymbolContextItem resolve_scope, + lldb_private::SymbolContextList &sc_list) override; void FindGlobalVariables(lldb_private::ConstString name, diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index 4df5140bd7e1..9130eed63e43 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -8,7 +8,7 @@ #include "SymbolVendorELF.h" -#include <string.h> +#include <cstring> #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" #include "lldb/Core/Module.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp index 67a1ef5e4e51..2b2840796579 100644 --- a/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp @@ -8,7 +8,7 @@ #include "SymbolVendorWasm.h" -#include <string.h> +#include <cstring> #include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" #include "lldb/Core/Module.h" diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp new file mode 100644 index 000000000000..45d6f3b0e098 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.cpp @@ -0,0 +1,41 @@ +//===-- ThreadPostMortemTrace.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ThreadPostMortemTrace.h" + +#include <memory> + +#include "Plugins/Process/Utility/RegisterContextHistory.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" + +using namespace lldb; +using namespace lldb_private; + +void ThreadPostMortemTrace::RefreshStateAfterStop() {} + +RegisterContextSP ThreadPostMortemTrace::GetRegisterContext() { + if (!m_reg_context_sp) + m_reg_context_sp = CreateRegisterContextForFrame(nullptr); + + return m_reg_context_sp; +} + +RegisterContextSP +ThreadPostMortemTrace::CreateRegisterContextForFrame(StackFrame *frame) { + // Eventually this will calculate the register context based on the current + // trace position. + return std::make_shared<RegisterContextHistory>( + *this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS); +} + +bool ThreadPostMortemTrace::CalculateStopInfo() { return false; } + +const FileSpec &ThreadPostMortemTrace::GetTraceFile() const { + return m_trace_file; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h new file mode 100644 index 000000000000..9cfe754ae0e4 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/ThreadPostMortemTrace.h @@ -0,0 +1,60 @@ +//===-- ThreadPostMortemTrace.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_THREADPOSTMORTEMTRACE_H +#define LLDB_TARGET_THREADPOSTMORTEMTRACE_H + +#include "lldb/Target/Thread.h" + +namespace lldb_private { + +/// \class ThreadPostMortemTrace ThreadPostMortemTrace.h +/// +/// Thread implementation used for representing threads gotten from trace +/// session files, which are similar to threads from core files. +/// +/// See \a TraceSessionFileParser for more information regarding trace session +/// files. +class ThreadPostMortemTrace : public Thread { +public: + /// \param[in] process + /// The process who owns this thread. + /// + /// \param[in] tid + /// The tid of this thread. + /// + /// \param[in] trace_file + /// The file that contains the list of instructions that were traced when + /// this thread was being executed. + ThreadPostMortemTrace(Process &process, lldb::tid_t tid, + const FileSpec &trace_file) + : Thread(process, tid), m_trace_file(trace_file) {} + + void RefreshStateAfterStop() override; + + lldb::RegisterContextSP GetRegisterContext() override; + + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + + /// \return + /// The trace file of this thread. + const FileSpec &GetTraceFile() const; + +protected: + bool CalculateStopInfo() override; + + lldb::RegisterContextSP m_thread_reg_ctx_sp; + +private: + FileSpec m_trace_file; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_THREADPOSTMORTEMTRACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp new file mode 100644 index 000000000000..c88ad9dc6a59 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.cpp @@ -0,0 +1,224 @@ +//===-- TraceSessionFileParser.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===/ + +#include "TraceSessionFileParser.h" +#include "ThreadPostMortemTrace.h" + +#include <sstream> + +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; + +void TraceSessionFileParser::NormalizePath(lldb_private::FileSpec &file_spec) { + if (file_spec.IsRelative()) + file_spec.PrependPathComponent(m_session_file_dir); +} + +Error TraceSessionFileParser::ParseModule(lldb::TargetSP &target_sp, + const JSONModule &module) { + FileSpec system_file_spec(module.system_path); + NormalizePath(system_file_spec); + + FileSpec local_file_spec(module.file.hasValue() ? *module.file + : module.system_path); + NormalizePath(local_file_spec); + + ModuleSpec module_spec; + module_spec.GetFileSpec() = local_file_spec; + module_spec.GetPlatformFileSpec() = system_file_spec; + + if (module.uuid.hasValue()) + module_spec.GetUUID().SetFromStringRef(*module.uuid); + + Status error; + ModuleSP module_sp = + target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error); + + if (error.Fail()) + return error.ToError(); + + bool load_addr_changed = false; + module_sp->SetLoadAddress(*target_sp, module.load_address.value, false, + load_addr_changed); + return llvm::Error::success(); +} + +Error TraceSessionFileParser::CreateJSONError(json::Path::Root &root, + const json::Value &value) { + std::string err; + raw_string_ostream os(err); + root.printErrorContext(value, os); + return createStringError( + std::errc::invalid_argument, "%s\n\nContext:\n%s\n\nSchema:\n%s", + toString(root.getError()).c_str(), os.str().c_str(), m_schema.data()); +} + +std::string TraceSessionFileParser::BuildSchema(StringRef plugin_schema) { + std::ostringstream schema_builder; + schema_builder << "{\n \"trace\": "; + schema_builder << plugin_schema.data() << ","; + schema_builder << R"( + "processes": [ + { + "pid": integer, + "triple": string, // llvm-triple + "threads": [ + { + "tid": integer, + "traceFile": string + } + ], + "modules": [ + { + "systemPath": string, // original path of the module at runtime + "file"?: string, // copy of the file if not available at "systemPath" + "loadAddress": string, // string address in hex or decimal form + "uuid"?: string, + } + ] + } + ] + // Notes: + // All paths are either absolute or relative to the session file. +} +)"; + return schema_builder.str(); +} + +ThreadPostMortemTraceSP +TraceSessionFileParser::ParseThread(ProcessSP &process_sp, + const JSONThread &thread) { + lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid); + + FileSpec trace_file(thread.trace_file); + NormalizePath(trace_file); + + ThreadPostMortemTraceSP thread_sp = + std::make_shared<ThreadPostMortemTrace>(*process_sp, tid, trace_file); + process_sp->GetThreadList().AddThread(thread_sp); + return thread_sp; +} + +Expected<TraceSessionFileParser::ParsedProcess> +TraceSessionFileParser::ParseProcess(const JSONProcess &process) { + TargetSP target_sp; + Status error = m_debugger.GetTargetList().CreateTarget( + m_debugger, /*user_exe_path*/ StringRef(), process.triple, + eLoadDependentsNo, + /*platform_options*/ nullptr, target_sp); + + if (!target_sp) + return error.ToError(); + + ParsedProcess parsed_process; + parsed_process.target_sp = target_sp; + + ProcessSP process_sp = target_sp->CreateProcess( + /*listener*/ nullptr, "trace", + /*crash_file*/ nullptr, + /*can_connect*/ false); + + process_sp->SetID(static_cast<lldb::pid_t>(process.pid)); + + for (const JSONThread &thread : process.threads) + parsed_process.threads.push_back(ParseThread(process_sp, thread)); + + for (const JSONModule &module : process.modules) + if (Error err = ParseModule(target_sp, module)) + return std::move(err); + + if (!process.threads.empty()) + process_sp->GetThreadList().SetSelectedThreadByIndexID(0); + + // We invoke DidAttach to create a correct stopped state for the process and + // its threads. + ArchSpec process_arch; + process_sp->DidAttach(process_arch); + + return parsed_process; +} + +Expected<std::vector<TraceSessionFileParser::ParsedProcess>> +TraceSessionFileParser::ParseCommonSessionFile( + const JSONTraceSessionBase &session) { + std::vector<ParsedProcess> parsed_processes; + + auto onError = [&]() { + // Delete all targets that were created so far in case of failures + for (ParsedProcess &parsed_process : parsed_processes) + m_debugger.GetTargetList().DeleteTarget(parsed_process.target_sp); + }; + + for (const JSONProcess &process : session.processes) { + if (Expected<ParsedProcess> parsed_process = ParseProcess(process)) + parsed_processes.push_back(std::move(*parsed_process)); + else { + onError(); + return parsed_process.takeError(); + } + } + return parsed_processes; +} + +namespace llvm { +namespace json { + +bool fromJSON(const Value &value, TraceSessionFileParser::JSONAddress &address, + Path path) { + Optional<StringRef> s = value.getAsString(); + if (s.hasValue() && !s->getAsInteger(0, address.value)) + return true; + + path.report("expected numeric string"); + return false; +} + +bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module, + Path path) { + ObjectMapper o(value, path); + return o && o.map("systemPath", module.system_path) && + o.map("file", module.file) && + o.map("loadAddress", module.load_address) && + o.map("uuid", module.uuid); +} + +bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread, + Path path) { + ObjectMapper o(value, path); + return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file); +} + +bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process, + Path path) { + ObjectMapper o(value, path); + return o && o.map("pid", process.pid) && o.map("triple", process.triple) && + o.map("threads", process.threads) && o.map("modules", process.modules); +} + +bool fromJSON(const Value &value, + TraceSessionFileParser::JSONTracePluginSettings &plugin_settings, + Path path) { + ObjectMapper o(value, path); + return o && o.map("type", plugin_settings.type); +} + +bool fromJSON(const Value &value, + TraceSessionFileParser::JSONTraceSessionBase &session, + Path path) { + ObjectMapper o(value, path); + return o && o.map("processes", session.processes); +} + +} // namespace json +} // namespace llvm diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h b/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h new file mode 100644 index 000000000000..6abaffcecd3a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/common/TraceSessionFileParser.h @@ -0,0 +1,179 @@ +//===-- TraceSessionFileParser.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TARGET_TRACESESSIONPARSER_H +#define LLDB_TARGET_TRACESESSIONPARSER_H + +#include "llvm/Support/JSON.h" + +#include "ThreadPostMortemTrace.h" + +namespace lldb_private { + +/// \class TraceSessionFileParser TraceSessionFileParser.h +/// +/// Base class for parsing the common information of JSON trace session files. +/// Contains the basic C++ structs that represent the JSON data, which include +/// \a JSONTraceSession as the root object. +/// +/// See \a Trace::FindPlugin for more information regarding these JSON files. +class TraceSessionFileParser { +public: + /// C++ structs representing the JSON trace session. + /// \{ + struct JSONAddress { + lldb::addr_t value; + }; + + struct JSONModule { + std::string system_path; + llvm::Optional<std::string> file; + JSONAddress load_address; + llvm::Optional<std::string> uuid; + }; + + struct JSONThread { + int64_t tid; + std::string trace_file; + }; + + struct JSONProcess { + int64_t pid; + std::string triple; + std::vector<JSONThread> threads; + std::vector<JSONModule> modules; + }; + + struct JSONTracePluginSettings { + std::string type; + }; + + struct JSONTraceSessionBase { + std::vector<JSONProcess> processes; + }; + + /// The trace plug-in implementation should provide its own TPluginSettings, + /// which corresponds to the "trace" section of the schema. + template <class TPluginSettings> + struct JSONTraceSession : JSONTraceSessionBase { + TPluginSettings trace; + }; + /// \} + + /// Helper struct holding the objects created when parsing a process + struct ParsedProcess { + lldb::TargetSP target_sp; + std::vector<lldb::ThreadPostMortemTraceSP> threads; + }; + + TraceSessionFileParser(Debugger &debugger, llvm::StringRef session_file_dir, + llvm::StringRef schema) + : m_debugger(debugger), m_session_file_dir(session_file_dir), + m_schema(schema) {} + + /// Build the full schema for a Trace plug-in. + /// + /// \param[in] plugin_schema + /// The subschema that corresponds to the "trace" section of the schema. + /// + /// \return + /// The full schema containing the common attributes and the plug-in + /// specific attributes. + static std::string BuildSchema(llvm::StringRef plugin_schema); + + /// Parse the fields common to all trace session schemas. + /// + /// \param[in] session + /// The session json objects already deserialized. + /// + /// \return + /// A list of \a ParsedProcess containing all threads and targets created + /// during the parsing, or an error in case of failures. In case of + /// errors, no side effects are produced. + llvm::Expected<std::vector<ParsedProcess>> + ParseCommonSessionFile(const JSONTraceSessionBase &session); + +protected: + /// Resolve non-absolute paths relative to the session file folder. It + /// modifies the given file_spec. + void NormalizePath(lldb_private::FileSpec &file_spec); + + lldb::ThreadPostMortemTraceSP ParseThread(lldb::ProcessSP &process_sp, + const JSONThread &thread); + + llvm::Expected<ParsedProcess> ParseProcess(const JSONProcess &process); + + llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module); + + /// Create a user-friendly error message upon a JSON-parsing failure using the + /// \a json::ObjectMapper functionality. + /// + /// \param[in] root + /// The \a llvm::json::Path::Root used to parse the JSON \a value. + /// + /// \param[in] value + /// The json value that failed to parse. + /// + /// \return + /// An \a llvm::Error containing the user-friendly error message. + llvm::Error CreateJSONError(llvm::json::Path::Root &root, + const llvm::json::Value &value); + + Debugger &m_debugger; + std::string m_session_file_dir; + llvm::StringRef m_schema; +}; +} // namespace lldb_private + +namespace llvm { +namespace json { + +bool fromJSON(const Value &value, + lldb_private::TraceSessionFileParser::JSONAddress &address, + Path path); + +bool fromJSON(const Value &value, + lldb_private::TraceSessionFileParser::JSONModule &module, + Path path); + +bool fromJSON(const Value &value, + lldb_private::TraceSessionFileParser::JSONThread &thread, + Path path); + +bool fromJSON(const Value &value, + lldb_private::TraceSessionFileParser::JSONProcess &process, + Path path); + +bool fromJSON(const Value &value, + lldb_private::TraceSessionFileParser::JSONTracePluginSettings + &plugin_settings, + Path path); + +bool fromJSON( + const Value &value, + lldb_private::TraceSessionFileParser::JSONTraceSessionBase &session, + Path path); + +template <class TPluginSettings> +bool fromJSON( + const Value &value, + lldb_private::TraceSessionFileParser::JSONTraceSession<TPluginSettings> + &session, + Path path) { + ObjectMapper o(value, path); + return o && o.map("trace", session.trace) && + fromJSON(value, + (lldb_private::TraceSessionFileParser::JSONTraceSessionBase &) + session, + path); +} + +} // namespace json +} // namespace llvm + +#endif // LLDB_TARGET_TRACESESSIONPARSER_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp index e1758dfcfc41..5650af657c5e 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp @@ -8,7 +8,10 @@ #include "CommandObjectTraceStartIntelPT.h" +#include "TraceIntelPT.h" +#include "TraceIntelPTConstants.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Target/Process.h" #include "lldb/Target/Trace.h" using namespace lldb; @@ -16,10 +19,12 @@ using namespace lldb_private; using namespace lldb_private::trace_intel_pt; using namespace llvm; +// CommandObjectThreadTraceStartIntelPT + #define LLDB_OPTIONS_thread_trace_start_intel_pt #include "TraceIntelPTCommandOptions.inc" -Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue( +Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) { Status error; @@ -27,23 +32,27 @@ Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue( switch (short_option) { case 's': { - int32_t size_in_kb; - if (option_arg.empty() || option_arg.getAsInteger(0, size_in_kb) || - size_in_kb < 0) + int64_t thread_buffer_size; + if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) || + thread_buffer_size < 0) error.SetErrorStringWithFormat("invalid integer value for option '%s'", option_arg.str().c_str()); else - m_size_in_kb = size_in_kb; + m_thread_buffer_size = thread_buffer_size; + break; + } + case 't': { + m_enable_tsc = true; break; } - case 'c': { - int32_t custom_config; - if (option_arg.empty() || option_arg.getAsInteger(0, custom_config) || - custom_config < 0) + case 'p': { + int64_t psb_period; + if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) || + psb_period < 0) error.SetErrorStringWithFormat("invalid integer value for option '%s'", option_arg.str().c_str()); else - m_custom_config = custom_config; + m_psb_period = psb_period; break; } default: @@ -52,22 +61,104 @@ Status CommandObjectTraceStartIntelPT::CommandOptions::SetOptionValue( return error; } -void CommandObjectTraceStartIntelPT::CommandOptions::OptionParsingStarting( - ExecutionContext *execution_context) { - m_size_in_kb = 4; - m_custom_config = 0; +void CommandObjectThreadTraceStartIntelPT::CommandOptions:: + OptionParsingStarting(ExecutionContext *execution_context) { + m_thread_buffer_size = kDefaultThreadBufferSize; + m_enable_tsc = kDefaultEnableTscValue; + m_psb_period = kDefaultPsbPeriod; } llvm::ArrayRef<OptionDefinition> -CommandObjectTraceStartIntelPT::CommandOptions::GetDefinitions() { +CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() { return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options); } -bool CommandObjectTraceStartIntelPT::HandleOneThread( - lldb::tid_t tid, CommandReturnObject &result) { - result.AppendMessageWithFormat( - "would trace tid %" PRIu64 " with size_in_kb %zu and custom_config %d\n", - tid, m_options.m_size_in_kb, m_options.m_custom_config); - result.SetStatus(eReturnStatusSuccessFinishResult); +bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads( + Args &command, CommandReturnObject &result, + llvm::ArrayRef<lldb::tid_t> tids) { + if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size, + m_options.m_enable_tsc, m_options.m_psb_period)) + result.SetError(Status(std::move(err))); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + + return result.Succeeded(); +} + +/// CommandObjectProcessTraceStartIntelPT + +#define LLDB_OPTIONS_process_trace_start_intel_pt +#include "TraceIntelPTCommandOptions.inc" + +Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 's': { + int64_t thread_buffer_size; + if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) || + thread_buffer_size < 0) + error.SetErrorStringWithFormat("invalid integer value for option '%s'", + option_arg.str().c_str()); + else + m_thread_buffer_size = thread_buffer_size; + break; + } + case 'l': { + int64_t process_buffer_size_limit; + if (option_arg.empty() || + option_arg.getAsInteger(0, process_buffer_size_limit) || + process_buffer_size_limit < 0) + error.SetErrorStringWithFormat("invalid integer value for option '%s'", + option_arg.str().c_str()); + else + m_process_buffer_size_limit = process_buffer_size_limit; + break; + } + case 't': { + m_enable_tsc = true; + break; + } + case 'p': { + int64_t psb_period; + if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) || + psb_period < 0) + error.SetErrorStringWithFormat("invalid integer value for option '%s'", + option_arg.str().c_str()); + else + m_psb_period = psb_period; + break; + } + default: + llvm_unreachable("Unimplemented option"); + } + return error; +} + +void CommandObjectProcessTraceStartIntelPT::CommandOptions:: + OptionParsingStarting(ExecutionContext *execution_context) { + m_thread_buffer_size = kDefaultThreadBufferSize; + m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit; + m_enable_tsc = kDefaultEnableTscValue; + m_psb_period = kDefaultPsbPeriod; +} + +llvm::ArrayRef<OptionDefinition> +CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() { + return llvm::makeArrayRef(g_process_trace_start_intel_pt_options); +} + +bool CommandObjectProcessTraceStartIntelPT::DoExecute( + Args &command, CommandReturnObject &result) { + if (Error err = m_trace.Start(m_options.m_thread_buffer_size, + m_options.m_process_buffer_size_limit, + m_options.m_enable_tsc, m_options.m_psb_period)) + result.SetError(Status(std::move(err))); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h index 265569c553fa..2f3d53a86406 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h @@ -9,21 +9,21 @@ #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTRACESTARTINTELPT_H -#include "../../../../source/Commands/CommandObjectThreadUtil.h" +#include "../../../../source/Commands/CommandObjectTrace.h" +#include "TraceIntelPT.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" namespace lldb_private { namespace trace_intel_pt { -class CommandObjectTraceStartIntelPT : public CommandObjectIterateOverThreads { +class CommandObjectThreadTraceStartIntelPT + : public CommandObjectMultipleThreads { public: class CommandOptions : public Options { public: CommandOptions() : Options() { OptionParsingStarting(nullptr); } - ~CommandOptions() override = default; - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override; @@ -31,31 +31,76 @@ public: llvm::ArrayRef<OptionDefinition> GetDefinitions() override; - size_t m_size_in_kb; - uint32_t m_custom_config; + size_t m_thread_buffer_size; + bool m_enable_tsc; + llvm::Optional<size_t> m_psb_period; }; - CommandObjectTraceStartIntelPT(CommandInterpreter &interpreter) - : CommandObjectIterateOverThreads( + CommandObjectThreadTraceStartIntelPT(TraceIntelPT &trace, + CommandInterpreter &interpreter) + : CommandObjectMultipleThreads( interpreter, "thread trace start", "Start tracing one or more threads with intel-pt. " "Defaults to the current thread. Thread indices can be " "specified as arguments.\n Use the thread-index \"all\" to trace " - "all threads.", + "all threads including future threads.", "thread trace start [<thread-index> <thread-index> ...] " "[<intel-pt-options>]", lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock | lldb::eCommandProcessMustBeLaunched | lldb::eCommandProcessMustBePaused), - m_options() {} + m_trace(trace), m_options() {} + + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecuteOnThreads(Args &command, CommandReturnObject &result, + llvm::ArrayRef<lldb::tid_t> tids) override; + + TraceIntelPT &m_trace; + CommandOptions m_options; +}; + +class CommandObjectProcessTraceStartIntelPT : public CommandObjectParsed { +public: + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } - ~CommandObjectTraceStartIntelPT() override = default; + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override; + + size_t m_thread_buffer_size; + size_t m_process_buffer_size_limit; + bool m_enable_tsc; + llvm::Optional<size_t> m_psb_period; + }; + + CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace, + CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "process trace start", + "Start tracing this process with intel-pt, including future " + "threads. " + "This is implemented by tracing each thread independently. " + "Threads traced with the \"thread trace start\" command are left " + "unaffected ant not retraced.", + "process trace start [<intel-pt-options>]", + lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock | + lldb::eCommandProcessMustBeLaunched | + lldb::eCommandProcessMustBePaused), + m_trace(trace), m_options() {} Options *GetOptions() override { return &m_options; } protected: - bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override; + bool DoExecute(Args &command, CommandReturnObject &result) override; + TraceIntelPT &m_trace; CommandOptions m_options; }; diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp index 6b8b06564052..4822a786c68c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -8,8 +8,13 @@ #include "DecodedThread.h" +#include <intel-pt.h> +#include <memory> + +#include "TraceCursorIntelPT.h" #include "lldb/Utility/StreamString.h" +using namespace lldb; using namespace lldb_private; using namespace lldb_private::trace_intel_pt; using namespace llvm; @@ -30,12 +35,21 @@ void IntelPTError::log(llvm::raw_ostream &OS) const { OS << "error: " << libipt_error_message; } +IntelPTInstruction::IntelPTInstruction(llvm::Error err) { + llvm::handleAllErrors(std::move(err), + [&](std::unique_ptr<llvm::ErrorInfoBase> info) { + m_error = std::move(info); + }); + m_pt_insn.ip = LLDB_INVALID_ADDRESS; + m_pt_insn.iclass = ptic_error; +} + bool IntelPTInstruction::IsError() const { return (bool)m_error; } -Expected<lldb::addr_t> IntelPTInstruction::GetLoadAddress() const { - if (IsError()) - return ToError(); - return m_pt_insn.ip; +lldb::addr_t IntelPTInstruction::GetLoadAddress() const { return m_pt_insn.ip; } + +Optional<uint64_t> IntelPTInstruction::GetTimestampCounter() const { + return m_timestamp; } Error IntelPTInstruction::ToError() const { @@ -47,18 +61,58 @@ Error IntelPTInstruction::ToError() const { return make_error<StringError>(m_error->message(), m_error->convertToErrorCode()); } +size_t DecodedThread::GetRawTraceSize() const { return m_raw_trace_size; } + +TraceInstructionControlFlowType +IntelPTInstruction::GetControlFlowType(lldb::addr_t next_load_address) const { + if (IsError()) + return (TraceInstructionControlFlowType)0; -size_t DecodedThread::GetLastPosition() const { - return m_instructions.empty() ? 0 : m_instructions.size() - 1; + TraceInstructionControlFlowType mask = + eTraceInstructionControlFlowTypeInstruction; + + switch (m_pt_insn.iclass) { + case ptic_cond_jump: + case ptic_jump: + case ptic_far_jump: + mask |= eTraceInstructionControlFlowTypeBranch; + if (m_pt_insn.ip + m_pt_insn.size != next_load_address) + mask |= eTraceInstructionControlFlowTypeTakenBranch; + break; + case ptic_return: + case ptic_far_return: + mask |= eTraceInstructionControlFlowTypeReturn; + break; + case ptic_call: + case ptic_far_call: + mask |= eTraceInstructionControlFlowTypeCall; + break; + default: + break; + } + + return mask; } ArrayRef<IntelPTInstruction> DecodedThread::GetInstructions() const { return makeArrayRef(m_instructions); } -size_t DecodedThread::GetCursorPosition() const { return m_position; } +DecodedThread::DecodedThread(ThreadSP thread_sp, Error error) + : m_thread_sp(thread_sp) { + m_instructions.emplace_back(std::move(error)); +} + +DecodedThread::DecodedThread(ThreadSP thread_sp, + std::vector<IntelPTInstruction> &&instructions, + size_t raw_trace_size) + : m_thread_sp(thread_sp), m_instructions(std::move(instructions)), + m_raw_trace_size(raw_trace_size) { + if (m_instructions.empty()) + m_instructions.emplace_back( + createStringError(inconvertibleErrorCode(), "empty trace")); +} -size_t DecodedThread::SetCursorPosition(size_t new_position) { - m_position = std::min(new_position, GetLastPosition()); - return m_position; +lldb::TraceCursorUP DecodedThread::GetCursor() { + return std::make_unique<TraceCursorIntelPT>(m_thread_sp, shared_from_this()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h index 3c7e030414cb..592c402cd0e5 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h @@ -15,6 +15,7 @@ #include "llvm/Support/Error.h" #include "lldb/Target/Trace.h" +#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" #include "intel-pt.h" @@ -60,17 +61,15 @@ private: /// As mentioned, any gap is represented as an error in this class. class IntelPTInstruction { public: + IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp) + : m_pt_insn(pt_insn), m_timestamp(timestamp) {} + IntelPTInstruction(const pt_insn &pt_insn) : m_pt_insn(pt_insn) {} /// Error constructor /// /// libipt errors should use the underlying \a IntelPTError class. - IntelPTInstruction(llvm::Error err) { - llvm::handleAllErrors(std::move(err), - [&](std::unique_ptr<llvm::ErrorInfoBase> info) { - m_error = std::move(info); - }); - } + IntelPTInstruction(llvm::Error err); /// Check if this object represents an error (i.e. a gap). /// @@ -79,15 +78,34 @@ public: bool IsError() const; /// \return - /// The instruction pointer address, or an \a llvm::Error if it is an - /// error. - llvm::Expected<lldb::addr_t> GetLoadAddress() const; + /// The instruction pointer address, or \a LLDB_INVALID_ADDRESS if it is + /// an error. + lldb::addr_t GetLoadAddress() const; /// \return /// An \a llvm::Error object if this class corresponds to an Error, or an /// \a llvm::Error::success otherwise. llvm::Error ToError() const; + /// Get the timestamp associated with the current instruction. The timestamp + /// is similar to what a rdtsc instruction would return. + /// + /// \return + /// The timestamp or \b llvm::None if not available. + llvm::Optional<uint64_t> GetTimestampCounter() const; + + /// Get the \a lldb::TraceInstructionControlFlowType categories of the + /// instruction. + /// + /// \param[in] next_load_address + /// The address of the next instruction in the trace or \b + /// LLDB_INVALID_ADDRESS if not available. + /// + /// \return + /// The control flow categories, or \b 0 if the instruction is an error. + lldb::TraceInstructionControlFlowType + GetControlFlowType(lldb::addr_t next_load_address) const; + IntelPTInstruction(IntelPTInstruction &&other) = default; private: @@ -95,6 +113,7 @@ private: const IntelPTInstruction &operator=(const IntelPTInstruction &other) = delete; pt_insn m_pt_insn; + llvm::Optional<uint64_t> m_timestamp; std::unique_ptr<llvm::ErrorInfoBase> m_error; }; @@ -105,11 +124,15 @@ private: /// /// Each decoded thread contains a cursor to the current position the user is /// stopped at. See \a Trace::GetCursorPosition for more information. -class DecodedThread { +class DecodedThread : public std::enable_shared_from_this<DecodedThread> { public: - DecodedThread(std::vector<IntelPTInstruction> &&instructions) - : m_instructions(std::move(instructions)), m_position(GetLastPosition()) { - } + DecodedThread(lldb::ThreadSP thread_sp, + std::vector<IntelPTInstruction> &&instructions, + size_t raw_trace_size); + + /// Constructor with a single error signaling a complete failure of the + /// decoding process. + DecodedThread(lldb::ThreadSP thread_sp, llvm::Error error); /// Get the instructions from the decoded trace. Some of them might indicate /// errors (i.e. gaps) in the trace. @@ -118,28 +141,23 @@ public: /// The instructions of the trace. llvm::ArrayRef<IntelPTInstruction> GetInstructions() const; - /// \return - /// The current position of the cursor of this trace, or 0 if there are no - /// instructions. - size_t GetCursorPosition() const; + /// Get a new cursor for the decoded thread. + lldb::TraceCursorUP GetCursor(); - /// Change the position of the cursor of this trace. If this value is to high, - /// the new position will be set as the last instruction of the trace. + /// Get the size in bytes of the corresponding Intel PT raw trace /// /// \return - /// The effective new position. - size_t SetCursorPosition(size_t new_position); - /// \} + /// The size of the trace. + size_t GetRawTraceSize() const; private: - /// \return - /// The index of the last element of the trace, or 0 if empty. - size_t GetLastPosition() const; - + lldb::ThreadSP m_thread_sp; std::vector<IntelPTInstruction> m_instructions; - size_t m_position; + size_t m_raw_trace_size; }; +using DecodedThreadSP = std::shared_ptr<DecodedThread>; + } // namespace trace_intel_pt } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp index b6e8ae808632..3827881454c7 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp @@ -1,5 +1,4 @@ -//===-- IntelPTDecoder.cpp --------------------------------------*- C++ -*-===// -// +//===-- IntelPTDecoder.cpp --======----------------------------------------===// // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -10,10 +9,13 @@ #include "llvm/Support/MemoryBuffer.h" +#include "../common/ThreadPostMortemTrace.h" +#include "DecodedThread.h" +#include "TraceIntelPT.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Target/Target.h" -#include "lldb/Target/ThreadTrace.h" +#include "lldb/Utility/StringExtractor.h" using namespace lldb; using namespace lldb_private; @@ -85,7 +87,7 @@ static int ProcessPTEvents(pt_insn_decoder &decoder, int errcode) { return errcode; } return 0; -}; +} /// Decode all the instructions from a configured decoder. /// The decoding flow is based on @@ -135,7 +137,23 @@ DecodeInstructions(pt_insn_decoder &decoder) { break; } - instructions.emplace_back(insn); + uint64_t time; + int time_error = pt_insn_time(&decoder, &time, nullptr, nullptr); + if (time_error == -pte_invalid) { + // This happens if we invoke the pt_insn_time method incorrectly, + // but the instruction is good though. + instructions.emplace_back( + make_error<IntelPTError>(time_error, insn.ip)); + instructions.emplace_back(insn); + break; + } + if (time_error == -pte_no_time) { + // We simply don't have time information, i.e. None of TSC, MTC or CYC + // was enabled. + instructions.emplace_back(insn); + } else { + instructions.emplace_back(insn, time); + } } } @@ -158,39 +176,26 @@ static int ReadProcessMemory(uint8_t *buffer, size_t size, return bytes_read; } -static std::vector<IntelPTInstruction> makeInstructionListFromError(Error err) { - std::vector<IntelPTInstruction> instructions; - instructions.emplace_back(std::move(err)); - return instructions; -} - -static std::vector<IntelPTInstruction> -CreateDecoderAndDecode(Process &process, const pt_cpu &pt_cpu, - const FileSpec &trace_file) { - ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error = - MemoryBuffer::getFile(trace_file.GetPath()); - if (std::error_code err = trace_or_error.getError()) - return makeInstructionListFromError(errorCodeToError(err)); - - MemoryBuffer &trace = **trace_or_error; +static Expected<std::vector<IntelPTInstruction>> +DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt, + MutableArrayRef<uint8_t> buffer) { + Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); + if (!cpu_info) + return cpu_info.takeError(); pt_config config; pt_config_init(&config); - config.cpu = pt_cpu; + config.cpu = *cpu_info; if (int errcode = pt_cpu_errata(&config.errata, &config.cpu)) - return makeInstructionListFromError(make_error<IntelPTError>(errcode)); + return make_error<IntelPTError>(errcode); - // The libipt library does not modify the trace buffer, hence the following - // cast is safe. - config.begin = - reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart())); - config.end = - reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferEnd())); + config.begin = buffer.data(); + config.end = buffer.data() + buffer.size(); pt_insn_decoder *decoder = pt_insn_alloc_decoder(&config); if (!decoder) - return makeInstructionListFromError(make_error<IntelPTError>(-pte_nomem)); + return make_error<IntelPTError>(-pte_nomem); pt_image *image = pt_insn_get_image(decoder); @@ -204,12 +209,71 @@ CreateDecoderAndDecode(Process &process, const pt_cpu &pt_cpu, return instructions; } -const DecodedThread &ThreadTraceDecoder::Decode() { - if (!m_decoded_thread.hasValue()) { - m_decoded_thread = DecodedThread( - CreateDecoderAndDecode(*m_trace_thread->GetProcess(), m_pt_cpu, - m_trace_thread->GetTraceFile())); - } +static Expected<std::vector<IntelPTInstruction>> +DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt, + const FileSpec &trace_file, size_t &raw_trace_size) { + ErrorOr<std::unique_ptr<MemoryBuffer>> trace_or_error = + MemoryBuffer::getFile(trace_file.GetPath()); + if (std::error_code err = trace_or_error.getError()) + return errorCodeToError(err); + + MemoryBuffer &trace = **trace_or_error; + MutableArrayRef<uint8_t> trace_data( + // The libipt library does not modify the trace buffer, hence the + // following cast is safe. + reinterpret_cast<uint8_t *>(const_cast<char *>(trace.getBufferStart())), + trace.getBufferSize()); + raw_trace_size = trace_data.size(); + return DecodeInMemoryTrace(process, trace_intel_pt, trace_data); +} + +static Expected<std::vector<IntelPTInstruction>> +DecodeLiveThread(Thread &thread, TraceIntelPT &trace, size_t &raw_trace_size) { + Expected<std::vector<uint8_t>> buffer = + trace.GetLiveThreadBuffer(thread.GetID()); + if (!buffer) + return buffer.takeError(); + raw_trace_size = buffer->size(); + if (Expected<pt_cpu> cpu_info = trace.GetCPUInfo()) + return DecodeInMemoryTrace(*thread.GetProcess(), trace, + MutableArrayRef<uint8_t>(*buffer)); + else + return cpu_info.takeError(); +} +DecodedThreadSP ThreadDecoder::Decode() { + if (!m_decoded_thread.hasValue()) + m_decoded_thread = DoDecode(); return *m_decoded_thread; } + +PostMortemThreadDecoder::PostMortemThreadDecoder( + const lldb::ThreadPostMortemTraceSP &trace_thread, TraceIntelPT &trace) + : m_trace_thread(trace_thread), m_trace(trace) {} + +DecodedThreadSP PostMortemThreadDecoder::DoDecode() { + size_t raw_trace_size = 0; + if (Expected<std::vector<IntelPTInstruction>> instructions = + DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace, + m_trace_thread->GetTraceFile(), raw_trace_size)) + return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(), + std::move(*instructions), + raw_trace_size); + else + return std::make_shared<DecodedThread>(m_trace_thread->shared_from_this(), + instructions.takeError()); +} + +LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace) + : m_thread_sp(thread.shared_from_this()), m_trace(trace) {} + +DecodedThreadSP LiveThreadDecoder::DoDecode() { + size_t raw_trace_size = 0; + if (Expected<std::vector<IntelPTInstruction>> instructions = + DecodeLiveThread(*m_thread_sp, m_trace, raw_trace_size)) + return std::make_shared<DecodedThread>( + m_thread_sp, std::move(*instructions), raw_trace_size); + else + return std::make_shared<DecodedThread>(m_thread_sp, + instructions.takeError()); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h index 2e67f9bf6da7..e969db579e52 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.h @@ -12,38 +12,73 @@ #include "intel-pt.h" #include "DecodedThread.h" +#include "forward-declarations.h" #include "lldb/Target/Process.h" #include "lldb/Utility/FileSpec.h" namespace lldb_private { namespace trace_intel_pt { -/// \a lldb_private::ThreadTrace decoder that stores the output from decoding, -/// avoiding recomputations, as decoding is expensive. -class ThreadTraceDecoder { +/// Base class that handles the decoding of a thread and caches the result. +class ThreadDecoder { public: - /// \param[in] trace_thread - /// The thread whose trace file will be decoded. + virtual ~ThreadDecoder() = default; + + ThreadDecoder() = default; + + /// Decode the thread and store the result internally, to avoid + /// recomputations. /// - /// \param[in] pt_cpu - /// The libipt cpu used when recording the trace. - ThreadTraceDecoder(const std::shared_ptr<ThreadTrace> &trace_thread, - const pt_cpu &pt_cpu) - : m_trace_thread(trace_thread), m_pt_cpu(pt_cpu), m_decoded_thread() {} + /// \return + /// A \a DecodedThread instance. + DecodedThreadSP Decode(); - /// Decode the thread and store the result internally. + ThreadDecoder(const ThreadDecoder &other) = delete; + ThreadDecoder &operator=(const ThreadDecoder &other) = delete; + +protected: + /// Decode the thread. /// /// \return /// A \a DecodedThread instance. - const DecodedThread &Decode(); + virtual DecodedThreadSP DoDecode() = 0; + + llvm::Optional<DecodedThreadSP> m_decoded_thread; +}; + +/// Decoder implementation for \a lldb_private::ThreadPostMortemTrace, which are +/// non-live processes that come trace session files. +class PostMortemThreadDecoder : public ThreadDecoder { +public: + /// \param[in] trace_thread + /// The thread whose trace file will be decoded. + /// + /// \param[in] trace + /// The main Trace object who owns this decoder and its data. + PostMortemThreadDecoder(const lldb::ThreadPostMortemTraceSP &trace_thread, + TraceIntelPT &trace); + +private: + DecodedThreadSP DoDecode() override; + + lldb::ThreadPostMortemTraceSP m_trace_thread; + TraceIntelPT &m_trace; +}; + +class LiveThreadDecoder : public ThreadDecoder { +public: + /// \param[in] thread + /// The thread whose traces will be decoded. + /// + /// \param[in] trace + /// The main Trace object who owns this decoder and its data. + LiveThreadDecoder(Thread &thread, TraceIntelPT &trace); private: - ThreadTraceDecoder(const ThreadTraceDecoder &other) = delete; - ThreadTraceDecoder &operator=(const ThreadTraceDecoder &other) = delete; + DecodedThreadSP DoDecode() override; - std::shared_ptr<ThreadTrace> m_trace_thread; - pt_cpu m_pt_cpu; - llvm::Optional<DecodedThread> m_decoded_thread; + lldb::ThreadSP m_thread_sp; + TraceIntelPT &m_trace; }; } // namespace trace_intel_pt diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp new file mode 100644 index 000000000000..edefdd0d3486 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -0,0 +1,100 @@ +//===-- TraceCursorIntelPT.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TraceCursorIntelPT.h" +#include "DecodedThread.h" +#include "TraceIntelPT.h" + +#include <cstdlib> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::trace_intel_pt; +using namespace llvm; + +TraceCursorIntelPT::TraceCursorIntelPT(ThreadSP thread_sp, + DecodedThreadSP decoded_thread_sp) + : TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp) { + assert(!m_decoded_thread_sp->GetInstructions().empty() && + "a trace should have at least one instruction or error"); + m_pos = m_decoded_thread_sp->GetInstructions().size() - 1; +} + +size_t TraceCursorIntelPT::GetInternalInstructionSize() { + return m_decoded_thread_sp->GetInstructions().size(); +} + +bool TraceCursorIntelPT::Next() { + auto canMoveOne = [&]() { + if (IsForwards()) + return m_pos + 1 < GetInternalInstructionSize(); + return m_pos > 0; + }; + + size_t initial_pos = m_pos; + + while (canMoveOne()) { + m_pos += IsForwards() ? 1 : -1; + if (!m_ignore_errors && IsError()) + return true; + if (GetInstructionControlFlowType() & m_granularity) + return true; + } + + // Didn't find any matching instructions + m_pos = initial_pos; + return false; +} + +size_t TraceCursorIntelPT::Seek(int64_t offset, SeekType origin) { + int64_t last_index = GetInternalInstructionSize() - 1; + + auto fitPosToBounds = [&](int64_t raw_pos) -> int64_t { + return std::min(std::max((int64_t)0, raw_pos), last_index); + }; + + switch (origin) { + case TraceCursor::SeekType::Set: + m_pos = fitPosToBounds(offset); + return m_pos; + case TraceCursor::SeekType::End: + m_pos = fitPosToBounds(offset + last_index); + return last_index - m_pos; + case TraceCursor::SeekType::Current: + int64_t new_pos = fitPosToBounds(offset + m_pos); + int64_t dist = m_pos - new_pos; + m_pos = new_pos; + return std::abs(dist); + } +} + +bool TraceCursorIntelPT::IsError() { + return m_decoded_thread_sp->GetInstructions()[m_pos].IsError(); +} + +Error TraceCursorIntelPT::GetError() { + return m_decoded_thread_sp->GetInstructions()[m_pos].ToError(); +} + +lldb::addr_t TraceCursorIntelPT::GetLoadAddress() { + return m_decoded_thread_sp->GetInstructions()[m_pos].GetLoadAddress(); +} + +Optional<uint64_t> TraceCursorIntelPT::GetTimestampCounter() { + return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter(); +} + +TraceInstructionControlFlowType +TraceCursorIntelPT::GetInstructionControlFlowType() { + lldb::addr_t next_load_address = + m_pos + 1 < GetInternalInstructionSize() + ? m_decoded_thread_sp->GetInstructions()[m_pos + 1].GetLoadAddress() + : LLDB_INVALID_ADDRESS; + return m_decoded_thread_sp->GetInstructions()[m_pos].GetControlFlowType( + next_load_address); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h new file mode 100644 index 000000000000..29d3792bb489 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h @@ -0,0 +1,50 @@ +//===-- TraceCursorIntelPT.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H +#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H + +#include "IntelPTDecoder.h" +#include "TraceIntelPTSessionFileParser.h" + +namespace lldb_private { +namespace trace_intel_pt { + +class TraceCursorIntelPT : public TraceCursor { +public: + TraceCursorIntelPT(lldb::ThreadSP thread_sp, + DecodedThreadSP decoded_thread_sp); + + size_t Seek(int64_t offset, SeekType origin) override; + + virtual bool Next() override; + + llvm::Error GetError() override; + + lldb::addr_t GetLoadAddress() override; + + llvm::Optional<uint64_t> GetTimestampCounter() override; + + lldb::TraceInstructionControlFlowType + GetInstructionControlFlowType() override; + + bool IsError() override; + +private: + size_t GetInternalInstructionSize(); + + /// Storage of the actual instructions + DecodedThreadSP m_decoded_thread_sp; + /// Internal instruction index currently pointing at. + size_t m_pos; +}; + +} // namespace trace_intel_pt +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACECURSORINTELPT_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp index 63a8b2dff4a7..c12bcd3523e3 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp @@ -8,12 +8,14 @@ #include "TraceIntelPT.h" +#include "../common/ThreadPostMortemTrace.h" #include "CommandObjectTraceStartIntelPT.h" +#include "DecodedThread.h" +#include "TraceIntelPTConstants.h" #include "TraceIntelPTSessionFileParser.h" #include "lldb/Core/PluginManager.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" -#include "lldb/Target/ThreadTrace.h" using namespace lldb; using namespace lldb_private; @@ -22,18 +24,27 @@ using namespace llvm; LLDB_PLUGIN_DEFINE(TraceIntelPT) -CommandObjectSP GetStartCommand(CommandInterpreter &interpreter) { - return CommandObjectSP(new CommandObjectTraceStartIntelPT(interpreter)); +lldb::CommandObjectSP +TraceIntelPT::GetProcessTraceStartCommand(CommandInterpreter &interpreter) { + return CommandObjectSP( + new CommandObjectProcessTraceStartIntelPT(*this, interpreter)); +} + +lldb::CommandObjectSP +TraceIntelPT::GetThreadTraceStartCommand(CommandInterpreter &interpreter) { + return CommandObjectSP( + new CommandObjectThreadTraceStartIntelPT(*this, interpreter)); } void TraceIntelPT::Initialize() { - PluginManager::RegisterPlugin( - GetPluginNameStatic(), "Intel Processor Trace", CreateInstance, - TraceIntelPTSessionFileParser::GetSchema(), GetStartCommand); + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace", + CreateInstanceForSessionFile, + CreateInstanceForLiveProcess, + TraceIntelPTSessionFileParser::GetSchema()); } void TraceIntelPT::Terminate() { - PluginManager::UnregisterPlugin(CreateInstance); + PluginManager::UnregisterPlugin(CreateInstanceForSessionFile); } ConstString TraceIntelPT::GetPluginNameStatic() { @@ -55,60 +66,278 @@ uint32_t TraceIntelPT::GetPluginVersion() { return 1; } void TraceIntelPT::Dump(Stream *s) const {} -Expected<TraceSP> -TraceIntelPT::CreateInstance(const json::Value &trace_session_file, - StringRef session_file_dir, Debugger &debugger) { +Expected<TraceSP> TraceIntelPT::CreateInstanceForSessionFile( + const json::Value &trace_session_file, StringRef session_file_dir, + Debugger &debugger) { return TraceIntelPTSessionFileParser(debugger, trace_session_file, session_file_dir) .Parse(); } +Expected<TraceSP> TraceIntelPT::CreateInstanceForLiveProcess(Process &process) { + TraceSP instance(new TraceIntelPT(process)); + process.GetTarget().SetTrace(instance); + return instance; +} + TraceIntelPT::TraceIntelPT( - const pt_cpu &pt_cpu, - const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads) - : m_pt_cpu(pt_cpu) { - for (const std::shared_ptr<ThreadTrace> &thread : traced_threads) - m_trace_threads.emplace( - std::piecewise_construct, - std::forward_as_tuple(thread->GetProcess()->GetID(), thread->GetID()), - std::forward_as_tuple(thread, pt_cpu)); -} - -const DecodedThread *TraceIntelPT::Decode(const Thread &thread) { - auto it = m_trace_threads.find( - std::make_pair(thread.GetProcess()->GetID(), thread.GetID())); - if (it == m_trace_threads.end()) - return nullptr; - return &it->second.Decode(); -} - -size_t TraceIntelPT::GetCursorPosition(const Thread &thread) { - const DecodedThread *decoded_thread = Decode(thread); - if (!decoded_thread) - return 0; - return decoded_thread->GetCursorPosition(); -} - -void TraceIntelPT::TraverseInstructions( - const Thread &thread, size_t position, TraceDirection direction, - std::function<bool(size_t index, Expected<lldb::addr_t> load_addr)> - callback) { - const DecodedThread *decoded_thread = Decode(thread); - if (!decoded_thread) - return; + const pt_cpu &cpu_info, + const std::vector<ThreadPostMortemTraceSP> &traced_threads) + : m_cpu_info(cpu_info) { + for (const ThreadPostMortemTraceSP &thread : traced_threads) + m_thread_decoders.emplace( + thread.get(), std::make_unique<PostMortemThreadDecoder>(thread, *this)); +} + +DecodedThreadSP TraceIntelPT::Decode(Thread &thread) { + RefreshLiveProcessState(); + if (m_live_refresh_error.hasValue()) + return std::make_shared<DecodedThread>( + thread.shared_from_this(), + createStringError(inconvertibleErrorCode(), *m_live_refresh_error)); + + auto it = m_thread_decoders.find(&thread); + if (it == m_thread_decoders.end()) + return std::make_shared<DecodedThread>( + thread.shared_from_this(), + createStringError(inconvertibleErrorCode(), "thread not traced")); + return it->second->Decode(); +} - ArrayRef<IntelPTInstruction> instructions = decoded_thread->GetInstructions(); +lldb::TraceCursorUP TraceIntelPT::GetCursor(Thread &thread) { + return Decode(thread)->GetCursor(); +} - ssize_t delta = direction == TraceDirection::Forwards ? 1 : -1; - for (ssize_t i = position; i < (ssize_t)instructions.size() && i >= 0; - i += delta) - if (!callback(i, instructions[i].GetLoadAddress())) - break; +void TraceIntelPT::DumpTraceInfo(Thread &thread, Stream &s, bool verbose) { + Optional<size_t> raw_size = GetRawTraceSize(thread); + s.Printf("\nthread #%u: tid = %" PRIu64, thread.GetIndexID(), thread.GetID()); + if (!raw_size) { + s.Printf(", not traced\n"); + return; + } + s.Printf("\n Raw trace size: %zu bytes\n", *raw_size); + return; } -size_t TraceIntelPT::GetInstructionCount(const Thread &thread) { - if (const DecodedThread *decoded_thread = Decode(thread)) - return decoded_thread->GetInstructions().size(); +Optional<size_t> TraceIntelPT::GetRawTraceSize(Thread &thread) { + if (IsTraced(thread)) + return Decode(thread)->GetRawTraceSize(); else - return 0; + return None; +} + +Expected<pt_cpu> TraceIntelPT::GetCPUInfoForLiveProcess() { + Expected<std::vector<uint8_t>> cpu_info = GetLiveProcessBinaryData("cpuInfo"); + if (!cpu_info) + return cpu_info.takeError(); + + int64_t cpu_family = -1; + int64_t model = -1; + int64_t stepping = -1; + std::string vendor_id; + + StringRef rest(reinterpret_cast<const char *>(cpu_info->data()), + cpu_info->size()); + while (!rest.empty()) { + StringRef line; + std::tie(line, rest) = rest.split('\n'); + + SmallVector<StringRef, 2> columns; + line.split(columns, StringRef(":"), -1, false); + + if (columns.size() < 2) + continue; // continue searching + + columns[1] = columns[1].trim(" "); + if (columns[0].contains("cpu family") && + columns[1].getAsInteger(10, cpu_family)) + continue; + + else if (columns[0].contains("model") && columns[1].getAsInteger(10, model)) + continue; + + else if (columns[0].contains("stepping") && + columns[1].getAsInteger(10, stepping)) + continue; + + else if (columns[0].contains("vendor_id")) { + vendor_id = columns[1].str(); + if (!vendor_id.empty()) + continue; + } + + if ((cpu_family != -1) && (model != -1) && (stepping != -1) && + (!vendor_id.empty())) { + return pt_cpu{vendor_id == "GenuineIntel" ? pcv_intel : pcv_unknown, + static_cast<uint16_t>(cpu_family), + static_cast<uint8_t>(model), + static_cast<uint8_t>(stepping)}; + } + } + return createStringError(inconvertibleErrorCode(), + "Failed parsing the target's /proc/cpuinfo file"); +} + +Expected<pt_cpu> TraceIntelPT::GetCPUInfo() { + if (!m_cpu_info) { + if (llvm::Expected<pt_cpu> cpu_info = GetCPUInfoForLiveProcess()) + m_cpu_info = *cpu_info; + else + return cpu_info.takeError(); + } + return *m_cpu_info; +} + +void TraceIntelPT::DoRefreshLiveProcessState( + Expected<TraceGetStateResponse> state) { + m_thread_decoders.clear(); + + if (!state) { + m_live_refresh_error = toString(state.takeError()); + return; + } + + for (const TraceThreadState &thread_state : state->tracedThreads) { + Thread &thread = + *m_live_process->GetThreadList().FindThreadByID(thread_state.tid); + m_thread_decoders.emplace( + &thread, std::make_unique<LiveThreadDecoder>(thread, *this)); + } +} + +bool TraceIntelPT::IsTraced(const Thread &thread) { + RefreshLiveProcessState(); + return m_thread_decoders.count(&thread); +} + +// The information here should match the description of the intel-pt section +// of the jLLDBTraceStart packet in the lldb/docs/lldb-gdb-remote.txt +// documentation file. Similarly, it should match the CLI help messages of the +// TraceIntelPTOptions.td file. +const char *TraceIntelPT::GetStartConfigurationHelp() { + return R"(Parameters: + + Note: If a parameter is not specified, a default value will be used. + + - int threadBufferSize (defaults to 4096 bytes): + [process and thread tracing] + Trace size in bytes per thread. It must be a power of 2 greater + than or equal to 4096 (2^12). The trace is circular keeping the + the most recent data. + + - boolean enableTsc (default to false): + [process and thread tracing] + Whether to use enable TSC timestamps or not. This is supported on + all devices that support intel-pt. + + - psbPeriod (defaults to null): + [process and thread tracing] + This value defines the period in which PSB packets will be generated. + A PSB packet is a synchronization packet that contains a TSC + timestamp and the current absolute instruction pointer. + + This parameter can only be used if + + /sys/bus/event_source/devices/intel_pt/caps/psb_cyc + + is 1. Otherwise, the PSB period will be defined by the processor. + + If supported, valid values for this period can be found in + + /sys/bus/event_source/devices/intel_pt/caps/psb_periods + + which contains a hexadecimal number, whose bits represent + valid values e.g. if bit 2 is set, then value 2 is valid. + + The psb_period value is converted to the approximate number of + raw trace bytes between PSB packets as: + + 2 ^ (value + 11) + + e.g. value 3 means 16KiB between PSB packets. Defaults to 0 if + supported. + + - int processBufferSizeLimit (defaults to 500 MB): + [process tracing only] + Maximum total trace size per process in bytes. This limit applies + to the sum of the sizes of all thread traces of this process, + excluding the ones created explicitly with "thread tracing". + Whenever a thread is attempted to be traced due to this command + and the limit would be reached, the process is stopped with a + "processor trace" reason, so that the user can retrace the process + if needed.)"; +} + +Error TraceIntelPT::Start(size_t thread_buffer_size, + size_t total_buffer_size_limit, bool enable_tsc, + Optional<size_t> psb_period) { + TraceIntelPTStartRequest request; + request.threadBufferSize = thread_buffer_size; + request.processBufferSizeLimit = total_buffer_size_limit; + request.enableTsc = enable_tsc; + request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; }); + request.type = GetPluginName().AsCString(); + return Trace::Start(toJSON(request)); +} + +Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) { + size_t thread_buffer_size = kDefaultThreadBufferSize; + size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit; + bool enable_tsc = kDefaultEnableTscValue; + Optional<size_t> psb_period = kDefaultPsbPeriod; + + if (configuration) { + if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) { + dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size); + dict->GetValueForKeyAsInteger("processBufferSizeLimit", + process_buffer_size_limit); + dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc); + dict->GetValueForKeyAsInteger("psbPeriod", psb_period); + } else { + return createStringError(inconvertibleErrorCode(), + "configuration object is not a dictionary"); + } + } + + return Start(thread_buffer_size, process_buffer_size_limit, enable_tsc, + psb_period); +} + +llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids, + size_t thread_buffer_size, bool enable_tsc, + Optional<size_t> psb_period) { + TraceIntelPTStartRequest request; + request.threadBufferSize = thread_buffer_size; + request.enableTsc = enable_tsc; + request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; }); + request.type = GetPluginName().AsCString(); + request.tids.emplace(); + for (lldb::tid_t tid : tids) + request.tids->push_back(tid); + return Trace::Start(toJSON(request)); +} + +Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids, + StructuredData::ObjectSP configuration) { + size_t thread_buffer_size = kDefaultThreadBufferSize; + bool enable_tsc = kDefaultEnableTscValue; + Optional<size_t> psb_period = kDefaultPsbPeriod; + + if (configuration) { + if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) { + dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size); + dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc); + dict->GetValueForKeyAsInteger("psbPeriod", psb_period); + } else { + return createStringError(inconvertibleErrorCode(), + "configuration object is not a dictionary"); + } + } + + return Start(tids, thread_buffer_size, enable_tsc, psb_period); +} + +Expected<std::vector<uint8_t>> +TraceIntelPT::GetLiveThreadBuffer(lldb::tid_t tid) { + return Trace::GetLiveThreadBinaryData(tid, "threadTraceBuffer"); } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h index 5058e6fd32f2..e3b247112ae1 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h @@ -45,49 +45,134 @@ public: /// \return /// A trace instance or an error in case of failures. static llvm::Expected<lldb::TraceSP> - CreateInstance(const llvm::json::Value &trace_session_file, - llvm::StringRef session_file_dir, Debugger &debugger); + CreateInstanceForSessionFile(const llvm::json::Value &trace_session_file, + llvm::StringRef session_file_dir, + Debugger &debugger); + + static llvm::Expected<lldb::TraceSP> + CreateInstanceForLiveProcess(Process &process); static ConstString GetPluginNameStatic(); uint32_t GetPluginVersion() override; /// \} + lldb::CommandObjectSP + GetProcessTraceStartCommand(CommandInterpreter &interpreter) override; + + lldb::CommandObjectSP + GetThreadTraceStartCommand(CommandInterpreter &interpreter) override; + llvm::StringRef GetSchema() override; - void TraverseInstructions( - const Thread &thread, size_t position, TraceDirection direction, - std::function<bool(size_t index, llvm::Expected<lldb::addr_t> load_addr)> - callback) override; + lldb::TraceCursorUP GetCursor(Thread &thread) override; + + void DumpTraceInfo(Thread &thread, Stream &s, bool verbose) override; + + llvm::Optional<size_t> GetRawTraceSize(Thread &thread); + + void DoRefreshLiveProcessState( + llvm::Expected<TraceGetStateResponse> state) override; + + bool IsTraced(const Thread &thread) override; + + const char *GetStartConfigurationHelp() override; + + /// Start tracing a live process. + /// + /// \param[in] thread_buffer_size + /// Trace size per thread in bytes. + /// + /// \param[in] total_buffer_size_limit + /// Maximum total trace size per process in bytes. + /// More information in TraceIntelPT::GetStartConfigurationHelp(). + /// + /// \param[in] enable_tsc + /// Whether to use enable TSC timestamps or not. + /// More information in TraceIntelPT::GetStartConfigurationHelp(). + /// + /// \param[in] psb_period + /// + /// This value defines the period in which PSB packets will be generated. + /// More information in TraceIntelPT::GetStartConfigurationHelp(); + /// + /// \return + /// \a llvm::Error::success if the operation was successful, or + /// \a llvm::Error otherwise. + llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit, + bool enable_tsc, llvm::Optional<size_t> psb_period); + + /// \copydoc Trace::Start + llvm::Error Start(StructuredData::ObjectSP configuration = + StructuredData::ObjectSP()) override; - size_t GetInstructionCount(const Thread &thread) override; + /// Start tracing live threads. + /// + /// \param[in] tids + /// Threads to trace. + /// + /// \param[in] thread_buffer_size + /// Trace size per thread in bytes. + /// + /// \param[in] enable_tsc + /// Whether to use enable TSC timestamps or not. + /// More information in TraceIntelPT::GetStartConfigurationHelp(). + /// + /// \param[in] psb_period + /// + /// This value defines the period in which PSB packets will be generated. + /// More information in TraceIntelPT::GetStartConfigurationHelp(). + /// + /// \return + /// \a llvm::Error::success if the operation was successful, or + /// \a llvm::Error otherwise. + llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t thread_buffer_size, + bool enable_tsc, llvm::Optional<size_t> psb_period); + + /// \copydoc Trace::Start + llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, + StructuredData::ObjectSP configuration = + StructuredData::ObjectSP()) override; + + /// Get the thread buffer content for a live thread + llvm::Expected<std::vector<uint8_t>> GetLiveThreadBuffer(lldb::tid_t tid); - size_t GetCursorPosition(const Thread &thread) override; + llvm::Expected<pt_cpu> GetCPUInfo(); private: friend class TraceIntelPTSessionFileParser; + llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess(); + /// \param[in] trace_threads /// ThreadTrace instances, which are not live-processes and whose trace /// files are fixed. - TraceIntelPT(const pt_cpu &pt_cpu, - const std::vector<std::shared_ptr<ThreadTrace>> &traced_threads); + TraceIntelPT( + const pt_cpu &cpu_info, + const std::vector<lldb::ThreadPostMortemTraceSP> &traced_threads); + + /// Constructor for live processes + TraceIntelPT(Process &live_process) + : Trace(live_process), m_thread_decoders(){}; /// Decode the trace of the given thread that, i.e. recontruct the traced - /// instructions. That trace must be managed by this class. + /// instructions. /// /// \param[in] thread /// If \a thread is a \a ThreadTrace, then its internal trace file will be /// decoded. Live threads are not currently supported. /// /// \return - /// A \a DecodedThread instance if decoding was successful, or a \b - /// nullptr if the thread's trace is not managed by this class. - const DecodedThread *Decode(const Thread &thread); - - pt_cpu m_pt_cpu; - std::map<std::pair<lldb::pid_t, lldb::tid_t>, ThreadTraceDecoder> - m_trace_threads; + /// A \a DecodedThread shared pointer with the decoded instructions. Any + /// errors are embedded in the instruction list. + DecodedThreadSP Decode(Thread &thread); + + /// It is provided by either a session file or a live process' "cpuInfo" + /// binary data. + llvm::Optional<pt_cpu> m_cpu_info; + std::map<const Thread *, std::unique_ptr<ThreadDecoder>> m_thread_decoders; + /// Error gotten after a failed live process update, if any. + llvm::Optional<std::string> m_live_refresh_error; }; } // namespace trace_intel_pt diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h new file mode 100644 index 000000000000..c2bc1b57b2bd --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h @@ -0,0 +1,27 @@ +//===-- TraceIntelPTConstants.h ---------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H +#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H + +#include <cstddef> + +#include <llvm/ADT/Optional.h> + +namespace lldb_private { +namespace trace_intel_pt { + +const size_t kDefaultThreadBufferSize = 4 * 1024; // 4KB +const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB +const bool kDefaultEnableTscValue = false; +const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None; + +} // namespace trace_intel_pt +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td index 6ffe949dbe7b..9e8cab1ee5c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td @@ -1,16 +1,74 @@ include "../../../../source/Commands/OptionsBase.td" +// The information of the start commands here should match the description of +// the intel-pt section of the jLLDBTraceStart packet in the +// lldb/docs/lldb-gdb-remote.txt documentation file. Similarly, it should match +// the API help message of TraceIntelPT::GetStartConfigurationHelp(). + let Command = "thread trace start intel pt" in { def thread_trace_start_intel_pt_size: Option<"size", "s">, Group<1>, Arg<"Value">, - Desc<"The size of the trace in KB. The kernel rounds it down to the nearest" - " multiple of 4. Defaults to 4.">; - def thread_trace_start_intel_pt_custom_config: Option<"custom-config", "c">, + Desc<"Trace size in bytes per thread. It must be a power of 2 greater " + "than or equal to 4096 (2^12). The trace is circular keeping " + "the most recent data. Defaults to 4096 bytes.">; + def thread_trace_start_intel_pt_tsc: Option<"tsc", "t">, + Group<1>, + Desc<"Enable the use of TSC timestamps. This is supported on all devices " + "that support intel-pt.">; + def thread_trace_start_intel_pt_psb_period: Option<"psb-period", "p">, + Group<1>, + Arg<"Value">, + Desc<"This value defines the period in which PSB packets will be " + "generated. A PSB packet is a synchronization packet that contains a " + "TSC timestamp and the current absolute instruction pointer. " + "This parameter can only be used if " + "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, " + "the PSB period will be defined by the processor. If supported, valid " + "values for this period can be found in " + "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " + "contains a hexadecimal number, whose bits represent valid values " + "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is " + "converted to the approximate number of raw trace bytes between PSB " + "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB " + "packets. Defaults to 0 if supported.">; +} + +let Command = "process trace start intel pt" in { + def process_trace_start_intel_pt_thread_size: Option<"thread-size", "s">, + Group<1>, + Arg<"Value">, + Desc<"Trace size in bytes per thread. It must be a power of 2 greater " + "than or equal to 4096 (2^12). The trace is circular keeping " + "the most recent data. Defaults to 4096 bytes.">; + def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">, + Group<1>, + Arg<"Value">, + Desc<"Maximum total trace size per process in bytes. This limit applies to " + "the sum of the sizes of all thread traces of this process, excluding " + "the ones created with the \"thread trace start\" command. " + "Whenever a thread is attempted to be traced due to this command and " + "the limit would be reached, the process is stopped with a " + "\"processor trace\" reason, so that the user can retrace the process " + "if needed. Defaults to 500MB.">; + def process_trace_start_intel_pt_tsc: Option<"tsc", "t">, + Group<1>, + Desc<"Enable the use of TSC timestamps. This is supported on all devices " + "that support intel-pt.">; + def process_trace_start_intel_pt_psb_period: Option<"psb-period", "p">, Group<1>, Arg<"Value">, - Desc<"Low level bitmask configuration for the kernel based on the values " - "in `grep -H /sys/bus/event_source/devices/intel_pt/format/*`. " - "See https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/perf-intel-pt.txt" - " for more information. Defaults to 0.">; + Desc<"This value defines the period in which PSB packets will be " + "generated. A PSB packet is a synchronization packet that contains a " + "TSC timestamp and the current absolute instruction pointer. " + "This parameter can only be used if " + "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc is 1. Otherwise, " + "the PSB period will be defined by the processor. If supported, valid " + "values for this period can be found in " + "/sys/bus/event_source/devices/intel_pt/caps/psb_periods which " + "contains a hexadecimal number, whose bits represent valid values " + "e.g. if bit 2 is set, then value 2 is valid. The psb_period value is " + "converted to the approximate number of raw trace bytes between PSB " + "packets as: 2 ^ (value + 11), e.g. value 3 means 16KiB between PSB " + "packets. Defaults to 0 if supported.">; } diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp index beef5c3968ea..5af7c269d0cb 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp @@ -8,11 +8,11 @@ #include "TraceIntelPTSessionFileParser.h" +#include "../common/ThreadPostMortemTrace.h" #include "lldb/Core/Debugger.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadList.h" -#include "lldb/Target/ThreadTrace.h" using namespace lldb; using namespace lldb_private; @@ -24,7 +24,7 @@ StringRef TraceIntelPTSessionFileParser::GetSchema() { if (schema.empty()) { schema = TraceSessionFileParser::BuildSchema(R"({ "type": "intel-pt", - "pt_cpu": { + "cpuInfo": { "vendor": "intel" | "unknown", "family": integer, "model": integer, @@ -35,21 +35,22 @@ StringRef TraceIntelPTSessionFileParser::GetSchema() { return schema; } -pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) { - return {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown, - static_cast<uint16_t>(pt_cpu.family), - static_cast<uint8_t>(pt_cpu.model), - static_cast<uint8_t>(pt_cpu.stepping)}; +pt_cpu TraceIntelPTSessionFileParser::ParsePTCPU( + const JSONTraceIntelPTCPUInfo &cpu_info) { + return {cpu_info.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown, + static_cast<uint16_t>(cpu_info.family), + static_cast<uint8_t>(cpu_info.model), + static_cast<uint8_t>(cpu_info.stepping)}; } TraceSP TraceIntelPTSessionFileParser::CreateTraceIntelPTInstance( - const pt_cpu &pt_cpu, std::vector<ParsedProcess> &parsed_processes) { - std::vector<ThreadTraceSP> threads; + const pt_cpu &cpu_info, std::vector<ParsedProcess> &parsed_processes) { + std::vector<ThreadPostMortemTraceSP> threads; for (const ParsedProcess &parsed_process : parsed_processes) threads.insert(threads.end(), parsed_process.threads.begin(), parsed_process.threads.end()); - TraceSP trace_instance(new TraceIntelPT(pt_cpu, threads)); + TraceSP trace_instance(new TraceIntelPT(cpu_info, threads)); for (const ParsedProcess &parsed_process : parsed_processes) parsed_process.target_sp->SetTrace(trace_instance); @@ -64,7 +65,7 @@ Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() { if (Expected<std::vector<ParsedProcess>> parsed_processes = ParseCommonSessionFile(session)) - return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.pt_cpu), + return CreateTraceIntelPTInstance(ParsePTCPU(session.trace.cpuInfo), *parsed_processes); else return parsed_processes.takeError(); @@ -73,25 +74,34 @@ Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() { namespace llvm { namespace json { -bool fromJSON(const Value &value, - TraceIntelPTSessionFileParser::JSONPTCPU &pt_cpu, Path path) { - ObjectMapper o(value, path); - return o && o.map("vendor", pt_cpu.vendor) && - o.map("family", pt_cpu.family) && o.map("model", pt_cpu.model) && - o.map("stepping", pt_cpu.stepping); -} - bool fromJSON( const Value &value, TraceIntelPTSessionFileParser::JSONTraceIntelPTSettings &plugin_settings, Path path) { ObjectMapper o(value, path); - return o && o.map("pt_cpu", plugin_settings.pt_cpu) && + return o && o.map("cpuInfo", plugin_settings.cpuInfo) && fromJSON( value, (TraceSessionFileParser::JSONTracePluginSettings &)plugin_settings, path); } +bool fromJSON(const json::Value &value, + TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info, + Path path) { + ObjectMapper o(value, path); + return o && o.map("vendor", cpu_info.vendor) && + o.map("family", cpu_info.family) && o.map("model", cpu_info.model) && + o.map("stepping", cpu_info.stepping); +} + +Value toJSON( + const TraceIntelPTSessionFileParser::JSONTraceIntelPTCPUInfo &cpu_info) { + return Value(Object{{"family", cpu_info.family}, + {"model", cpu_info.model}, + {"stepping", cpu_info.stepping}, + {"vendor", cpu_info.vendor}}); +} + } // namespace json } // namespace llvm diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h index 6a896de09d00..b2667a882222 100644 --- a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h @@ -10,7 +10,8 @@ #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H #include "TraceIntelPT.h" -#include "lldb/Target/TraceSessionFileParser.h" + +#include "../common/TraceSessionFileParser.h" namespace lldb_private { namespace trace_intel_pt { @@ -19,16 +20,16 @@ class TraceIntelPT; class TraceIntelPTSessionFileParser : public TraceSessionFileParser { public: - struct JSONPTCPU { - std::string vendor; + struct JSONTraceIntelPTCPUInfo { int64_t family; int64_t model; int64_t stepping; + std::string vendor; }; struct JSONTraceIntelPTSettings : TraceSessionFileParser::JSONTracePluginSettings { - JSONPTCPU pt_cpu; + JSONTraceIntelPTCPUInfo cpuInfo; }; /// See \a TraceSessionFileParser::TraceSessionFileParser for the description @@ -52,11 +53,11 @@ public: llvm::Expected<lldb::TraceSP> Parse(); lldb::TraceSP - CreateTraceIntelPTInstance(const pt_cpu &pt_cpu, + CreateTraceIntelPTInstance(const pt_cpu &cpu_info, std::vector<ParsedProcess> &parsed_processes); private: - pt_cpu ParsePTCPU(const JSONPTCPU &pt_cpu); + static pt_cpu ParsePTCPU(const JSONTraceIntelPTCPUInfo &cpu_info); const llvm::json::Value &m_trace_session_file; }; @@ -67,17 +68,20 @@ private: namespace llvm { namespace json { -bool fromJSON( - const Value &value, - lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::JSONPTCPU - &pt_cpu, - Path path); - bool fromJSON(const Value &value, lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser:: JSONTraceIntelPTSettings &plugin_settings, Path path); +bool fromJSON(const llvm::json::Value &value, + lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser:: + JSONTraceIntelPTCPUInfo &packet, + llvm::json::Path path); + +llvm::json::Value +toJSON(const lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser:: + JSONTraceIntelPTCPUInfo &packet); + } // namespace json } // namespace llvm diff --git a/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h new file mode 100644 index 000000000000..3c5f811acc10 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/forward-declarations.h @@ -0,0 +1,20 @@ +//===-- forward-declarations.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H +#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H + +namespace lldb_private { +namespace trace_intel_pt { + +class TraceIntelPT; +class ThreadDecoder; + +} // namespace trace_intel_pt +} // namespace lldb_private +#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_FORWARD_DECLARATIONS_H diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp new file mode 100644 index 000000000000..3dd4c89e2777 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp @@ -0,0 +1,66 @@ +//===-- CommandObjectThreadTraceExportCTF.cpp -----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CommandObjectThreadTraceExportCTF.h" + +#include "lldb/Host/OptionParser.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::ctf; +using namespace llvm; + +// CommandObjectThreadTraceExportCTF + +#define LLDB_OPTIONS_thread_trace_export_ctf +#include "TraceExporterCTFCommandOptions.inc" + +Status CommandObjectThreadTraceExportCTF::CommandOptions::SetOptionValue( + uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 't': { + int64_t thread_index; + if (option_arg.empty() || option_arg.getAsInteger(0, thread_index) || + thread_index < 0) + error.SetErrorStringWithFormat("invalid integer value for option '%s'", + option_arg.str().c_str()); + else + m_thread_index = thread_index; + break; + } + default: + llvm_unreachable("Unimplemented option"); + } + return error; +} + +void CommandObjectThreadTraceExportCTF::CommandOptions::OptionParsingStarting( + ExecutionContext *execution_context) { + m_thread_index = None; +} + +llvm::ArrayRef<OptionDefinition> +CommandObjectThreadTraceExportCTF::CommandOptions::GetDefinitions() { + return llvm::makeArrayRef(g_thread_trace_export_ctf_options); +} + +bool CommandObjectThreadTraceExportCTF::DoExecute(Args &command, + CommandReturnObject &result) { + Stream &s = result.GetOutputStream(); + // TODO: create an actual instance of the exporter and invoke it + if (m_options.m_thread_index) + s.Printf("got thread index %d\n", (int)m_options.m_thread_index.getValue()); + else + s.Printf("didn't get a thread index\n"); + + return result.Succeeded(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h new file mode 100644 index 000000000000..26b068a8f8c5 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.h @@ -0,0 +1,56 @@ +//===-- CommandObjectThreadTraceExportCTF.h -------------------*- C++ //-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H +#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H + +#include "TraceExporterCTF.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" + +namespace lldb_private { +namespace ctf { + +class CommandObjectThreadTraceExportCTF : public CommandObjectParsed { +public: + class CommandOptions : public Options { + public: + CommandOptions() : Options() { OptionParsingStarting(nullptr); } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override; + + void OptionParsingStarting(ExecutionContext *execution_context) override; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override; + + llvm::Optional<size_t> m_thread_index; + }; + + CommandObjectThreadTraceExportCTF(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "thread trace export ctf", + "Export a given thread's trace to Chrome Trace Format", + "thread trace export ctf [<ctf-options>]", + lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock | + lldb::eCommandProcessMustBeLaunched | + lldb::eCommandProcessMustBePaused), + m_options() {} + + Options *GetOptions() override { return &m_options; } + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override; + + CommandOptions m_options; +}; + +} // namespace ctf +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_COMMANDOBJECTTHREADTRACEEXPORTCTF_H diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp new file mode 100644 index 000000000000..08bc03d78303 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.cpp @@ -0,0 +1,53 @@ +//===-- TraceExporterCTF.cpp ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TraceExporterCTF.h" + +#include <memory> + +#include "CommandObjectThreadTraceExportCTF.h" +#include "lldb/Core/PluginManager.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::ctf; +using namespace llvm; + +LLDB_PLUGIN_DEFINE(TraceExporterCTF) + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ + +static CommandObjectSP +GetThreadTraceExportCommand(CommandInterpreter &interpreter) { + return std::make_shared<CommandObjectThreadTraceExportCTF>(interpreter); +} + +void TraceExporterCTF::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "Chrome Trace Format Exporter", CreateInstance, + GetThreadTraceExportCommand); +} + +void TraceExporterCTF::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ConstString TraceExporterCTF::GetPluginNameStatic() { + static ConstString g_name("ctf"); + return g_name; +} + +ConstString TraceExporterCTF::GetPluginName() { return GetPluginNameStatic(); } + +uint32_t TraceExporterCTF::GetPluginVersion() { return 1; } + +Expected<TraceExporterUP> TraceExporterCTF::CreateInstance() { + return std::make_unique<TraceExporterCTF>(); +} diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h new file mode 100644 index 000000000000..8f9e354ab0dd --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTF.h @@ -0,0 +1,42 @@ +//===-- TraceExporterCTF.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H +#define LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H + +#include "lldb/Target/TraceExporter.h" + +namespace lldb_private { +namespace ctf { + +/// Trace Exporter Plugin that can produce traces in Chrome Trace Format. +/// Still in development. +class TraceExporterCTF : public TraceExporter { +public: + ~TraceExporterCTF() override = default; + + /// PluginInterface protocol + /// \{ + static llvm::Expected<lldb::TraceExporterUP> CreateInstance(); + + ConstString GetPluginName() override; + + static void Initialize(); + + static void Terminate(); + + static ConstString GetPluginNameStatic(); + + uint32_t GetPluginVersion() override; + /// \} +}; + +} // namespace ctf +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_TRACE_EXPORTER_CTF_H diff --git a/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td new file mode 100644 index 000000000000..ce751f148d9f --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/TraceExporter/ctf/TraceExporterCTFOptions.td @@ -0,0 +1,9 @@ +include "../../../../source/Commands/OptionsBase.td" + +let Command = "thread trace export ctf" in { + def thread_trace_export_ctf: Option<"tid", "t">, + Group<1>, + Arg<"ThreadIndex">, + Desc<"Export the trace for the specified thread index. Otherwise, the " + "currently selected thread will be used.">; +} diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 0218606b8937..d4260a966857 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -75,7 +75,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" #include "Plugins/SymbolFile/PDB/PDBASTParser.h" -#include <stdio.h> +#include <cstdio> #include <mutex> @@ -163,7 +163,6 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) { if (name.getNameKind() == clang::DeclarationName::CXXDestructorName) if (auto *baseDtorDecl = base_record->getDestructor()) { if (baseDtorDecl->isVirtual()) { - path.Decls = baseDtorDecl; decls.push_back(baseDtorDecl); return true; } else @@ -171,12 +170,11 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) { } // Otherwise, search for name in the base class. - for (path.Decls = base_record->lookup(name); !path.Decls.empty(); - path.Decls = path.Decls.slice(1)) { + for (path.Decls = base_record->lookup(name).begin(); + path.Decls != path.Decls.end(); ++path.Decls) { if (auto *method_decl = - llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front())) + llvm::dyn_cast<clang::CXXMethodDecl>(*path.Decls)) if (method_decl->isVirtual() && !isOverload(decl, method_decl)) { - path.Decls = method_decl; decls.push_back(method_decl); return true; } @@ -479,6 +477,9 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { case clang::Language::OpenCL: LangStd = LangStandard::lang_opencl10; break; + case clang::Language::OpenCLCXX: + LangStd = LangStandard::lang_openclcpp; + break; case clang::Language::CUDA: LangStd = LangStandard::lang_cuda; break; @@ -686,8 +687,8 @@ void TypeSystemClang::SetTargetTriple(llvm::StringRef target_triple) { void TypeSystemClang::SetExternalSource( llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_up) { ASTContext &ast = getASTContext(); - ast.setExternalSource(ast_source_up); ast.getTranslationUnitDecl()->setHasExternalLexicalStorage(true); + ast.setExternalSource(ast_source_up); } ASTContext &TypeSystemClang::getASTContext() { @@ -745,7 +746,7 @@ void TypeSystemClang::CreateASTContext() { *m_diagnostics_engine_up, *m_file_manager_up); m_ast_up = std::make_unique<ASTContext>( *m_language_options_up, *m_source_manager_up, *m_identifier_table_up, - *m_selector_table_up, *m_builtins_up); + *m_selector_table_up, *m_builtins_up, TU_Complete); m_diagnostic_consumer_up = std::make_unique<NullDiagnosticConsumer>(); m_ast_up->getDiagnostics().setClient(m_diagnostic_consumer_up.get(), false); @@ -1356,9 +1357,11 @@ CompilerType TypeSystemClang::CreateRecordType( } namespace { - bool IsValueParam(const clang::TemplateArgument &argument) { - return argument.getKind() == TemplateArgument::Integral; - } +/// Returns true iff the given TemplateArgument should be represented as an +/// NonTypeTemplateParmDecl in the AST. +bool IsValueParam(const clang::TemplateArgument &argument) { + return argument.getKind() == TemplateArgument::Integral; +} } static TemplateParameterList *CreateTemplateParameterList( @@ -1462,6 +1465,99 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo( template_args_ptr, nullptr); } +/// Returns true if the given template parameter can represent the given value. +/// For example, `typename T` can represent `int` but not integral values such +/// as `int I = 3`. +static bool TemplateParameterAllowsValue(NamedDecl *param, + const TemplateArgument &value) { + if (auto *type_param = llvm::dyn_cast<TemplateTypeParmDecl>(param)) { + // Compare the argument kind, i.e. ensure that <typename> != <int>. + if (value.getKind() != TemplateArgument::Type) + return false; + } else if (auto *type_param = + llvm::dyn_cast<NonTypeTemplateParmDecl>(param)) { + // Compare the argument kind, i.e. ensure that <typename> != <int>. + if (!IsValueParam(value)) + return false; + // Compare the integral type, i.e. ensure that <int> != <char>. + if (type_param->getType() != value.getIntegralType()) + return false; + } else { + // There is no way to create other parameter decls at the moment, so we + // can't reach this case during normal LLDB usage. Log that this happened + // and assert. + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + LLDB_LOG(log, + "Don't know how to compare template parameter to passed" + " value. Decl kind of parameter is: {0}", + param->getDeclKindName()); + lldbassert(false && "Can't compare this TemplateParmDecl subclass"); + // In release builds just fall back to marking the parameter as not + // accepting the value so that we don't try to fit an instantiation to a + // template that doesn't fit. E.g., avoid that `S<1>` is being connected to + // `template<typename T> struct S;`. + return false; + } + return true; +} + +/// Returns true if the given class template declaration could produce an +/// instantiation with the specified values. +/// For example, `<typename T>` allows the arguments `float`, but not for +/// example `bool, float` or `3` (as an integer parameter value). +static bool ClassTemplateAllowsToInstantiationArgs( + ClassTemplateDecl *class_template_decl, + const TypeSystemClang::TemplateParameterInfos &instantiation_values) { + + TemplateParameterList ¶ms = *class_template_decl->getTemplateParameters(); + + // Save some work by iterating only once over the found parameters and + // calculate the information related to parameter packs. + + // Contains the first pack parameter (or non if there are none). + llvm::Optional<NamedDecl *> pack_parameter; + // Contains the number of non-pack parameters. + size_t non_pack_params = params.size(); + for (size_t i = 0; i < params.size(); ++i) { + NamedDecl *param = params.getParam(i); + if (param->isParameterPack()) { + pack_parameter = param; + non_pack_params = i; + break; + } + } + + // The found template needs to have compatible non-pack template arguments. + // E.g., ensure that <typename, typename> != <typename>. + // The pack parameters are compared later. + if (non_pack_params != instantiation_values.args.size()) + return false; + + // Ensure that <typename...> != <typename>. + if (pack_parameter.hasValue() != instantiation_values.hasParameterPack()) + return false; + + // Compare the first pack parameter that was found with the first pack + // parameter value. The special case of having an empty parameter pack value + // always fits to a pack parameter. + // E.g., ensure that <int...> != <typename...>. + if (pack_parameter && !instantiation_values.packed_args->args.empty() && + !TemplateParameterAllowsValue( + *pack_parameter, instantiation_values.packed_args->args.front())) + return false; + + // Compare all the non-pack parameters now. + // E.g., ensure that <int> != <long>. + for (const auto pair : llvm::zip_first(instantiation_values.args, params)) { + const TemplateArgument &passed_arg = std::get<0>(pair); + NamedDecl *found_param = std::get<1>(pair); + if (!TemplateParameterAllowsValue(found_param, passed_arg)) + return false; + } + + return class_template_decl; +} + ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( DeclContext *decl_ctx, OptionalClangModuleID owning_module, lldb::AccessType access_type, const char *class_name, int kind, @@ -1475,12 +1571,22 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( IdentifierInfo &identifier_info = ast.Idents.get(class_name); DeclarationName decl_name(&identifier_info); + // Search the AST for an existing ClassTemplateDecl that could be reused. clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); - for (NamedDecl *decl : result) { class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl); - if (class_template_decl) - return class_template_decl; + if (!class_template_decl) + continue; + // The class template has to be able to represents the instantiation + // values we received. Without this we might end up putting an instantiation + // with arguments such as <int, int> to a template such as: + // template<typename T> struct S; + // Connecting the instantiation to an incompatible template could cause + // problems later on. + if (!ClassTemplateAllowsToInstantiationArgs(class_template_decl, + template_param_infos)) + continue; + return class_template_decl; } llvm::SmallVector<NamedDecl *, 8> template_param_decls; @@ -1866,8 +1972,8 @@ TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false); SetOwningModule(using_decl, owning_module); clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create( - getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl, - target); + getASTContext(), current_decl_ctx, clang::SourceLocation(), + target->getDeclName(), using_decl, target); SetOwningModule(shadow_decl, owning_module); using_decl->addShadowDecl(shadow_decl); current_decl_ctx->addDecl(using_decl); @@ -2114,11 +2220,10 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration( return decl; } -void TypeSystemClang::SetFunctionParameters(FunctionDecl *function_decl, - ParmVarDecl **params, - unsigned num_params) { +void TypeSystemClang::SetFunctionParameters( + FunctionDecl *function_decl, llvm::ArrayRef<ParmVarDecl *> params) { if (function_decl) - function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params)); + function_decl->setParams(params); } CompilerType @@ -2470,42 +2575,6 @@ ClangASTMetadata *TypeSystemClang::GetMetadata(const clang::Type *object) { return nullptr; } -bool TypeSystemClang::SetTagTypeKind(clang::QualType tag_qual_type, - int kind) const { - const clang::Type *clang_type = tag_qual_type.getTypePtr(); - if (clang_type) { - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type); - if (tag_type) { - clang::TagDecl *tag_decl = - llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl()); - if (tag_decl) { - tag_decl->setTagKind((clang::TagDecl::TagKind)kind); - return true; - } - } - } - return false; -} - -bool TypeSystemClang::SetDefaultAccessForRecordFields( - clang::RecordDecl *record_decl, int default_accessibility, - int *assigned_accessibilities, size_t num_assigned_accessibilities) { - if (record_decl) { - uint32_t field_idx; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), - field_end = record_decl->field_end(), field_idx = 0; - field != field_end; ++field, ++field_idx) { - // If no accessibility was assigned, assign the correct one - if (field_idx < num_assigned_accessibilities && - assigned_accessibilities[field_idx] == clang::AS_none) - field->setAccess((clang::AccessSpecifier)default_accessibility); - } - return true; - } - return false; -} - clang::DeclContext * TypeSystemClang::GetDeclContextForType(const CompilerType &type) { return GetDeclContextForType(ClangUtil::GetQualType(type)); @@ -4697,7 +4766,6 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::Void: break; - case clang::BuiltinType::Bool: case clang::BuiltinType::Char_S: case clang::BuiltinType::SChar: case clang::BuiltinType::WChar_S: @@ -4708,6 +4776,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::Int128: return lldb::eEncodingSint; + case clang::BuiltinType::Bool: case clang::BuiltinType::Char_U: case clang::BuiltinType::UChar: case clang::BuiltinType::WChar_U: @@ -4889,6 +4958,75 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type, case clang::BuiltinType::SveFloat64x4: break; + // RISC-V V builtin types. + case clang::BuiltinType::RvvInt8mf8: + case clang::BuiltinType::RvvInt8mf4: + case clang::BuiltinType::RvvInt8mf2: + case clang::BuiltinType::RvvInt8m1: + case clang::BuiltinType::RvvInt8m2: + case clang::BuiltinType::RvvInt8m4: + case clang::BuiltinType::RvvInt8m8: + case clang::BuiltinType::RvvUint8mf8: + case clang::BuiltinType::RvvUint8mf4: + case clang::BuiltinType::RvvUint8mf2: + case clang::BuiltinType::RvvUint8m1: + case clang::BuiltinType::RvvUint8m2: + case clang::BuiltinType::RvvUint8m4: + case clang::BuiltinType::RvvUint8m8: + case clang::BuiltinType::RvvInt16mf4: + case clang::BuiltinType::RvvInt16mf2: + case clang::BuiltinType::RvvInt16m1: + case clang::BuiltinType::RvvInt16m2: + case clang::BuiltinType::RvvInt16m4: + case clang::BuiltinType::RvvInt16m8: + case clang::BuiltinType::RvvUint16mf4: + case clang::BuiltinType::RvvUint16mf2: + case clang::BuiltinType::RvvUint16m1: + case clang::BuiltinType::RvvUint16m2: + case clang::BuiltinType::RvvUint16m4: + case clang::BuiltinType::RvvUint16m8: + case clang::BuiltinType::RvvInt32mf2: + case clang::BuiltinType::RvvInt32m1: + case clang::BuiltinType::RvvInt32m2: + case clang::BuiltinType::RvvInt32m4: + case clang::BuiltinType::RvvInt32m8: + case clang::BuiltinType::RvvUint32mf2: + case clang::BuiltinType::RvvUint32m1: + case clang::BuiltinType::RvvUint32m2: + case clang::BuiltinType::RvvUint32m4: + case clang::BuiltinType::RvvUint32m8: + case clang::BuiltinType::RvvInt64m1: + case clang::BuiltinType::RvvInt64m2: + case clang::BuiltinType::RvvInt64m4: + case clang::BuiltinType::RvvInt64m8: + case clang::BuiltinType::RvvUint64m1: + case clang::BuiltinType::RvvUint64m2: + case clang::BuiltinType::RvvUint64m4: + case clang::BuiltinType::RvvUint64m8: + case clang::BuiltinType::RvvFloat16mf4: + case clang::BuiltinType::RvvFloat16mf2: + case clang::BuiltinType::RvvFloat16m1: + case clang::BuiltinType::RvvFloat16m2: + case clang::BuiltinType::RvvFloat16m4: + case clang::BuiltinType::RvvFloat16m8: + case clang::BuiltinType::RvvFloat32mf2: + case clang::BuiltinType::RvvFloat32m1: + case clang::BuiltinType::RvvFloat32m2: + case clang::BuiltinType::RvvFloat32m4: + case clang::BuiltinType::RvvFloat32m8: + case clang::BuiltinType::RvvFloat64m1: + case clang::BuiltinType::RvvFloat64m2: + case clang::BuiltinType::RvvFloat64m4: + case clang::BuiltinType::RvvFloat64m8: + case clang::BuiltinType::RvvBool1: + case clang::BuiltinType::RvvBool2: + case clang::BuiltinType::RvvBool4: + case clang::BuiltinType::RvvBool8: + case clang::BuiltinType::RvvBool16: + case clang::BuiltinType::RvvBool32: + case clang::BuiltinType::RvvBool64: + break; + case clang::BuiltinType::IncompleteMatrixIdx: break; } @@ -6365,7 +6503,7 @@ CompilerType TypeSystemClang::GetChildCompilerTypeAtIndex( case clang::Type::RValueReference: if (idx_is_valid) { const clang::ReferenceType *reference_type = - llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr()); + llvm::cast<clang::ReferenceType>(GetQualType(type).getTypePtr()); CompilerType pointee_clang_type = GetType(reference_type->getPointeeType()); if (transparent_pointers && pointee_clang_type.IsAggregateType()) { @@ -6536,10 +6674,11 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( if (cxx_record_decl->lookupInBases( [decl_name](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) { - path.Decls = - specifier->getType()->getAsCXXRecordDecl()->lookup( - decl_name); - return !path.Decls.empty(); + CXXRecordDecl *record = + specifier->getType()->getAsCXXRecordDecl(); + auto r = record->lookup(decl_name); + path.Decls = r.begin(); + return !r.empty(); }, paths)) { clang::CXXBasePaths::const_paths_iterator path, @@ -6562,9 +6701,10 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( ->getDecl()); } } - for (clang::NamedDecl *path_decl : path->Decls) { + for (clang::DeclContext::lookup_iterator I = path->Decls, E; + I != E; ++I) { child_idx = GetIndexForRecordChild( - parent_record_decl, path_decl, omit_empty_base_classes); + parent_record_decl, *I, omit_empty_base_classes); if (child_idx == UINT32_MAX) { child_indexes.clear(); return 0; @@ -9238,11 +9378,11 @@ CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl, std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName( void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) { std::vector<CompilerDecl> found_decls; - if (opaque_decl_ctx) { + SymbolFile *symbol_file = GetSymbolFile(); + if (opaque_decl_ctx && symbol_file) { DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx; std::set<DeclContext *> searched; std::multimap<DeclContext *, DeclContext *> search_queue; - SymbolFile *symbol_file = GetSymbolFile(); for (clang::DeclContext *decl_context = root_decl_ctx; decl_context != nullptr && found_decls.empty(); @@ -9336,10 +9476,10 @@ uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx, clang::DeclContext *child_decl_ctx, ConstString *child_name, CompilerType *child_type) { - if (frame_decl_ctx) { + SymbolFile *symbol_file = GetSymbolFile(); + if (frame_decl_ctx && symbol_file) { std::set<DeclContext *> searched; std::multimap<DeclContext *, DeclContext *> search_queue; - SymbolFile *symbol_file = GetSymbolFile(); // Get the lookup scope for the decl we're trying to find. clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent(); @@ -9585,7 +9725,8 @@ ScratchTypeSystemClang::ScratchTypeSystemClang(Target &target, llvm::Triple triple) : TypeSystemClang("scratch ASTContext", triple), m_triple(triple), m_target_wp(target.shared_from_this()), - m_persistent_variables(new ClangPersistentVariables) { + m_persistent_variables( + new ClangPersistentVariables(target.shared_from_this())) { m_scratch_ast_source_up = CreateASTSource(); m_scratch_ast_source_up->InstallASTContext(*this); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( @@ -9653,7 +9794,8 @@ ScratchTypeSystemClang::CreateUtilityFunction(std::string text, return {}; return std::make_unique<ClangUtilityFunction>( - *target_sp.get(), std::move(text), std::move(name)); + *target_sp.get(), std::move(text), std::move(name), + target_sp->GetDebugUtilityExpression()); } PersistentExpressionState * diff --git a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index d1d876d05a6b..4a6891795bd8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/contrib/llvm-project/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -9,7 +9,7 @@ #ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H #define LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLANG_TYPESYSTEMCLANG_H -#include <stdint.h> +#include <cstdint> #include <functional> #include <initializer_list> @@ -265,7 +265,7 @@ public: clang::DeclContext::lookup_result result = decl_context->lookup(myName); if (!result.empty()) { - clang::NamedDecl *named_decl = result[0]; + clang::NamedDecl *named_decl = *result.begin(); if (const RecordDeclType *record_decl = llvm::dyn_cast<RecordDeclType>(named_decl)) compiler_type.SetCompilerType( @@ -328,6 +328,8 @@ public: (!packed_args || !packed_args->packed_args); } + bool hasParameterPack() const { return static_cast<bool>(packed_args); } + llvm::SmallVector<const char *, 2> names; llvm::SmallVector<clang::TemplateArgument, 2> args; @@ -378,13 +380,6 @@ public: bool isForwardDecl, bool isInternal, ClangASTMetadata *metadata = nullptr); - bool SetTagTypeKind(clang::QualType type, int kind) const; - - bool SetDefaultAccessForRecordFields(clang::RecordDecl *record_decl, - int default_accessibility, - int *assigned_accessibilities, - size_t num_assigned_accessibilities); - // Returns a mask containing bits from the TypeSystemClang::eTypeXXX // enumerations @@ -421,7 +416,7 @@ public: int storage, bool add_decl = false); void SetFunctionParameters(clang::FunctionDecl *function_decl, - clang::ParmVarDecl **params, unsigned num_params); + llvm::ArrayRef<clang::ParmVarDecl *> params); CompilerType CreateBlockPointerType(const CompilerType &function_type); diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 1bc071c2b161..65947c5f833b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -38,10 +38,10 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly( ProcessSP process_sp(thread.GetProcess()); if (process_sp) { Status error; - const bool prefer_file_cache = true; + const bool force_live_memory = true; if (process_sp->GetTarget().ReadMemory( - range.GetBaseAddress(), prefer_file_cache, function_text.data(), - range.GetByteSize(), error) != range.GetByteSize()) { + range.GetBaseAddress(), function_text.data(), range.GetByteSize(), + error, force_live_memory) != range.GetByteSize()) { return false; } } diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp index fe1275d5b0cf..402a70cd025f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp @@ -51,12 +51,11 @@ bool UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly( ProcessSP process_sp(thread.GetProcess()); if (process_sp.get() == nullptr) return false; - const bool prefer_file_cache = true; std::vector<uint8_t> function_text(func.GetByteSize()); Status error; if (process_sp->GetTarget().ReadMemory( - func.GetBaseAddress(), prefer_file_cache, function_text.data(), - func.GetByteSize(), error) == func.GetByteSize()) { + func.GetBaseAddress(), function_text.data(), func.GetByteSize(), + error) == func.GetByteSize()) { RegisterContextSP reg_ctx(thread.GetRegisterContext()); m_assembly_inspection_engine->Initialize(reg_ctx); return m_assembly_inspection_engine->GetNonCallSiteUnwindPlanFromAssembly( @@ -153,12 +152,11 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite( return false; if (m_assembly_inspection_engine == nullptr) return false; - const bool prefer_file_cache = true; std::vector<uint8_t> function_text(func.GetByteSize()); Status error; if (process_sp->GetTarget().ReadMemory( - func.GetBaseAddress(), prefer_file_cache, function_text.data(), - func.GetByteSize(), error) == func.GetByteSize()) { + func.GetBaseAddress(), function_text.data(), func.GetByteSize(), + error) == func.GetByteSize()) { RegisterContextSP reg_ctx(thread.GetRegisterContext()); m_assembly_inspection_engine->Initialize(reg_ctx); return m_assembly_inspection_engine->AugmentUnwindPlanFromCallSite( @@ -185,10 +183,9 @@ bool UnwindAssembly_x86::GetFastUnwindPlan(AddressRange &func, Thread &thread, ProcessSP process_sp = thread.GetProcess(); if (process_sp) { Target &target(process_sp->GetTarget()); - const bool prefer_file_cache = true; Status error; - if (target.ReadMemory(func.GetBaseAddress(), prefer_file_cache, - opcode_data.data(), 4, error) == 4) { + if (target.ReadMemory(func.GetBaseAddress(), opcode_data.data(), 4, + error) == 4) { uint8_t i386_push_mov[] = {0x55, 0x89, 0xe5}; uint8_t x86_64_push_mov[] = {0x55, 0x48, 0x89, 0xe5}; @@ -220,12 +217,10 @@ bool UnwindAssembly_x86::FirstNonPrologueInsn( if (m_assembly_inspection_engine == nullptr) return false; - const bool prefer_file_cache = true; std::vector<uint8_t> function_text(func.GetByteSize()); Status error; - if (target->ReadMemory(func.GetBaseAddress(), prefer_file_cache, - function_text.data(), func.GetByteSize(), - error) == func.GetByteSize()) { + if (target->ReadMemory(func.GetBaseAddress(), function_text.data(), + func.GetByteSize(), error) == func.GetByteSize()) { size_t offset; if (m_assembly_inspection_engine->FindFirstNonPrologueInstruction( function_text.data(), func.GetByteSize(), offset)) { diff --git a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h index f39dce1afaa6..487748812968 100644 --- a/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h +++ b/contrib/llvm-project/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h @@ -45,9 +45,9 @@ public: /// are called. This one takes a vector of register name and lldb /// register numbers. struct lldb_reg_info { - const char *name; - uint32_t lldb_regnum; - lldb_reg_info() : name(nullptr), lldb_regnum(LLDB_INVALID_REGNUM) {} + const char *name = nullptr; + uint32_t lldb_regnum = LLDB_INVALID_REGNUM; + lldb_reg_info() = default; }; void Initialize(std::vector<lldb_reg_info> ®_info); |